自定义用户与权限管理之一
一般用户请忽略本节内容。
上一节已经讲述如何将用户数据存储在外部数据表中。
如果你需要更大的灵活性(通常没有这个必要了),也可以完全全抛开了foxtable自身的用户管理系统,自己重新设计一套用户管理系统。
本节内容完全采用SQL语言来实现,可以说是对SQL语言的一次大演练。
本节内容可以参考CaseStudy目录下的文件"自定义用户管理之一.Table",用户信息保存在一个Access文件"用户.mdb"中。
设计步骤
一、在文件“用户.mdb”新建一个名为“Users”的表,包括Name、Group、Password三列,分别 用于保存用户名、用户分组和密码。
二、建立一个外部数据源,连接到文件“用户.mdb”,数据源的名称设置为“User”。
三、打开Foxtable的用户管理,增加一个用户,并将其设置为默认用户,这样打开项目的时候,将不会出现foxtable的用户登录窗口。
提示:示例文件“自定义用户管理.Table"”菜单中的用户管理和用户登录,已经被自定义的用户管理和登录代替,必须先按Ctrl+Shift+F12回到系统菜单,才能打开Foxtable的用户管理。
四、在全局代码中定义两个变量:
Public
_UserName As String_UserName用户保存当前登录用户的名称,_UserGroup用于保存该用户的分组。
五、新建一个窗口名为“用户管理”窗口:
窗口的AfterLoad事件代码为:
Dim
cmd As New SQLCommand"增加用户"按钮的代码为:
Forms(
"增加用户").Open()“更改用户”按钮的代码为:
If
e.Form.Controls("ListBox1").SelectedIndex >=0 Then"删除用户“按钮的代码为:
Dim
lst As WinForm.ListBox = e.Form.Controls("ListBox1")六、新建一个名为"增加用户"的窗口:
"确定"按钮的代码设置为:
Dim
UserName As String = e.Form.Controls("UserName").Value七、新建一个名为“更改用户”的窗口:
窗口的AfterLoad事件代码为:
Dim
UserName As String
上面的代码在打开“更改用户”窗口之前,先判断“用户管理”窗口是否已经打开,如果已经打开,则更改“用户管理”窗口中选定的用户;否则更改当前登录的用户,且禁止更改用户名和用户分组,只能更改用户密码。
这样当我们需要给登录用户提供更改密码功能的时候,只需增加一个菜单按钮,按钮代码设置为:Forms("更改用户").Open()
"确定"按钮的代码为:
Dim
UserName As String = e.Form.Controls("UserName").Value八、增加一个名为“用户登录”的窗口:
窗口的AfterLoad事件代码为:
Dim
cmd As New SQLCommand"确定"按钮的代码为:
Dim
UserName As
String = e.Form.Controls("UserName").Value
Dim
cmd As
New SQLCommand
Dim
dt As
DataTable
Dim
dr As
DataRow
cmd.ConnectionName
= "User"
If
UserName = ""
Then
Messagebox.show("请选择用户!","提示",MessageBoxButtons.OK,MessageBoxIcon.Information)
Return
End
If
cmd.CommandText
= "Select * From {Users} Where [Name] = '"
& UserName
& "'"
dt =
cmd.ExecuteReader
If
dt.DataRows.Count
= 0 Then
Messagebox.show("此用户不存在!","提示",MessageBoxButtons.OK,MessageBoxIcon.Information)
Return
End
If
dr =
dt.DataRows(0)
If
e.Form.Controls("PassWord").Value
= dr("Password")
Then
_UserName =
UserName
_UserGroup =
dr("Group")
e.Form.Close
Else
Messagebox.show("密码错误!","提示",MessageBoxButtons.OK,MessageBoxIcon.Information)
End If
“取消”按钮的代码为:
e.Form.Close()
为了防止用户跳过确定和取消按钮,直接关闭窗口,请将窗口的“显示控制框”属性设置为False。
九、在项目事件AfterOpenProject中加入代码:
Forms(
"用户登录").Open()提示:为确保用户登录窗口为第一个打开的窗口,登录窗口的窗口类型必须设置为“模式”,且应该将其他所有独立或模式窗口的“自动打开”属性设置为False。
十、最后修改菜单中的"用户管理"和"切换用户"按钮的代码,启用"用户管理"按钮的代码为:
Forms(
"用户管理").Open()"切换用户"按钮的代码为:
Forms(
"用户登录").Open()你可以先应用系统菜单“system.ribbon”,然后再修改。
如果需要,还可以增加一个更改密码的按钮,代码设置为:
Forms("更改用户").Open()
总结
经过上述10个步骤的设计,我们已经建立了自己的用户管理和登录系统,用户登录后,用户名保存在全局变量_User中,用户分组保存在全局变量_UserGroup中。
我们只需对原来的权限代码稍作修改,即可适用自定义的用户管理系统,例如原来的代码为:
If User.Group =
"经理" Then
DataTables("表A").AllowEdit
= True
Else
DataTables("表A").AllowEdit
= False
End
If
现在只需改为:
If _UserGroup =
"经理" Then
DataTables("表A").AllowEdit
= True
Else
DataTables("表A").AllowEdit
= False
End
If
可以看出,自定义的用户管理系统,在应用上和内置的不会有任何差别。
不过使用自定义用户管理系统的时候,需要注意
事件触发顺序,由于自定义的用户登录窗口是在AfterOpenProject事件中打开,意味着在此事件之前触发执行的事件,是不能使用_UserName和_UserGroup变量的。
例如有的用户希望使用动态加载功能,在用户登录后,订单表只加载业务员为登录用户的订单,所有在项目事件BeforeLoadInnerTable设置了代码:
If
e.DataTableName = "订单" Then结果重新打开项目后,发现订单表根本没有加载任何数据,如果在代码中用MessageBox显示一下合成的加载条件:
If e.DataTableName
= "订单"
Then
e.Filter = "业务员 = '"
& _UserName & "'"
MessageBox.Show(e.Filter)
End If
会发现合成的加载条件为:
业务员 = ''
为什么会这样呢?
这是因为BeforeLoadInnerTable是在AfterOpenProject事件之前触发执行,此时_UserName还是空值。
显然 要实现我们的目标,得使用新的设计方法:
1、首先在BeforeLoadInnerTable事件加入下面的代码,确保订单表初始状态不会加载任何数据:
If
e.DataTableName = "订单" Then2、然后修改用户登录窗口的“确定”按钮的代码,在后面加上加载数据的代码:
Dim
UserName As String = e.Form.Controls("UserName").Value上面代码的最后两行,就是用于根据登录用户名动态加载订单表数据的:
DataTables("订单").LoadFilter
= "业务员 = '" & _UserName
& "'"
DataTables("订单").Load()
以下几个事件在AfterOpenProject事件之前触发执行:
BeforeOpenProject
BeforeConnectOuterDataSource
BeforeLoadInnerTable
BeforeLoadOuterTable
Initialize
另外
由于设置了默认用户,绕开了内置的登录窗口,而且菜单中的登录命令已经改为自定义的登录命令,所以用户将无法以开发者和管理员身份登录系统。
如果希望以开发者或管理员身份登录系统,可以在打开项目的过程中始终按住Ctrl键。
也可以考虑在菜单中另外加入一个系统登录命令,代码设置为:Syscmd.Project.Switchuser()
最后自定义用户登录显然不会触发LoadUserSetting事件,所以该事件中的代码应该移植到自定义用户登录窗口的"确定"按钮中。