U8门户开发手册
1. 功能概述
如何使伙伴二次开发的程序很好地和U8产品集成在一起?需要满足什么条件的程序才能和门户集成?如何开发一个满足这个条件的程序?本文将为您解答这些问题。
2. 名词解释
2.1菜单调整工具
功能:调整菜单位置;新增、修改、删除菜单(除U8系统菜单外)。 菜单调整工具在UAP中,通过菜单“工具->菜单调整工具”进入。
2.2 idt.dll文件
位置:在U8安装目录的Portal目录里。
该文件其实是一个xml文件,可以用任何文本编辑器打开。 其内容描述了双击每个末级菜单项目时需要调用的物理程序。
在872版本里,idt.dll并不在安装盘里,而是U8门户第一次运行时通过UFSystem..UA_IDT表里的内容动态生成的。当UFSystem..UA_IDT有变化时,U8门户会重新生成idt.dll文件。有了这种机制后,菜单调整工具就可以通过维护UFSystem..UA_IDT里的内容,从而达到维护idt.dll的目的。
3. 如何开发可与门户集成的VB dll
3.1代码修改
3.1.1引用工程UFPortalProxyInterface
文件位置:U8安装路径\\Portal\\UFPortalProxyInterface.dll
3.1.2相关代码修改
clsProductFacade文件为门户的入口文件,即在idt.dll文件后assembly项所对应的类名。如下所描述的:
然后在该接口的实现函数中转发调用原先工程中的Login,CallFunction,Logoff三个方法,具体参见后附的例子。在左树启动一项命令时依次调用Login和CallFunction。在门户退出或在权限管理中结束该产品时调用LogOff。
子系统必须自己维护是否已经进行了子系统登录过程,业务系统须维护子系统是否已经登录。
Login对象从g_business中通过调用GetVBclsLogin方法获得。 各接口含义如下:
1、Login接口( Private Function ILoginable_Login() As Boolean ),不管弹出的是模式窗体还是非模式窗体,此接口在成功登录后须返回True,而且要保证登录成功后,第二次调用此接口时也要返回True。只有在登录失败后方可返回False。也就是说此接口返回值的含义是是否已经成功登录子系统。
2、LogOff接口( Private Function ILoginable_LogOff() As Boolean ),此接口的含义是执行LogOff过程,如查成功使该子系统牌LogOff状态返回True,否则返回False。也就是说,如果该子统还未登录,则真接返回False就可以了。如果系统处于已经登录的过程,则执行业务组原有所需的LogOff过程,如果执行功能,正确LogOff了子系统,则返回True,否则返回False。如果在实际程序中没有此过程,则直接返回True即可。
3、CallFunction接口(Private Function ILoginable_CallFunction() As Boolean)。如果861产品没有子系统登录过程的产品,此值须返回True.
4、对于显示模式窗体的产品,如果已经申请了任务,请在模式窗体退出时自已清除任务。
实现这三个方法的例子如下:
Private Function ILoginable_Login() As Boolean If g_bLogined = True Then ILoginable_Login = True Exit Function
End If
If ((Not g_business Is Nothing) And g_bLogined = False) Then Dim oLoginTmp As Object Set oLoginTmp = g_business.GetVBclsLogin() Set g_oLogin = oLoginTmp ILoginable_Login = Login(oLoginTmp) If (ILoginable_Login = True) Then g_bLogined = True End If Else ILoginable_Login = Not g_business Is Nothing End If
End Function
Private Function ILoginable_LogOff() As Boolean If (g_bLogined = True) Then ILoginable_LogOff = LogOff() If (ILoginable_LogOff = True) Then g_bLogined = False End If Else ILoginable_LogOff = True End If
End Function
3.1.2.1增加Business属性
可读可写,且对大小写敏感。此属性维护一个对于此业务工程全局变量,以实现和VB程序和870Portal的交互。参考实现如下:
Public Property Get Business() As Object
Set Business = g_business
End Property
Public Property Set Business(busVal As Object)
Set g_business = busVal
End Property
3.1.2.2增加全局变量
新建一module文件,并加入如下全局变量: Public g_business As Object Public g_bLogined As Boolean
3.1.3三种窗体
3.1.3.1修改嵌入Portal的窗体文件 原来有MdiExtender控件的窗体 要嵌入Portal的窗体 修改方法:
调用CreateFormEnv方法 调用ShowForm方法
每个窗体都要有方法ExitForm
3.1.3.2修改第一次弹出就是模态的窗体
可以直接使用通过采用VB窗体的Form.Show (vbModal)的方式,也调用ShowForm方法来显示此窗体。
3.1.3.3由嵌入Portal的窗体弹出的窗体,
不作修改,如果是模式窗体,请在此窗体上加入UFFormPartner控件
3.1.4 UFToolbar的修改
3.1.4.1在Settoolbar之前将g_business传入 3.1.4.2在Settoolbar之前设置Tag信息
设置微软Toolbar每个Button的Tag信息 调用CreatePortalToolbarTag方法设置 示例 button.Tag =
CreatePortalToolbarTag(“ICON_NEW”,”ICOMMON”,”PortalToolbar”) 注意: 严禁创建多次 3.1.4.2.1图标
人机工程部给出完整的图标,并制定相应文件的命名规格 放在%U8SOFT%的icons目录下 直接使用图标的文件名(不需扩展名)
3.1.4.2.2分组
常用(ICOMMON):如打开、保存等 编辑(IEDIT):如增行、拷贝单元格等 处理(IDEAL):如审核、分单等 查询(ISEARCH):如过滤、联查等 3.1.4.2.3类型
PortalToolbar,目前填入此值即可。
3.1.4.3在窗体的Unload事件中加入 Set UFToolbar1.Business = Nothing
3.1.5中间过程
3.1.5.1判断窗体是否打开 FormIsOpened
3.1.5.2设置并激活某个已经存在的窗体
SetFormActive
3.1.5.3在显示过程中(窗体已经显示)关闭自身窗体
CloseForm
3.2常见问题
程序已经修改,双击门户节点时没有反应,调用状态进不了VB程序; 未正确修改clsProductFacade文件;
窗体已经嵌入到Portal中,但Toolbar的相关信息未转移到门户的工具栏上; 是否正确设置了每个Button的Tag信息;
3.3参考 3.3.1 ShowForm
显示嵌入Portal的窗体
Public Function ShowForm(ByVal obj As Object, ByVal SubID As String, ByVal sKey As String, Optional modalable As Boolean = False, Optional DockToProtal As Boolean = True, Optional ByVal vfd As Object) As String obj: Form对象; SubID: 子产品号;
sKey: Key,注意不能是form的Hwnd,在窗体的生命周期中,此值必须唯一; modalable: 该窗体是否为Model窗口; DockToProtal : 是否要嵌入到Portal中; vfd: 由CreateFormEnv对象的返回对象;
3.3.2 CreateFormEnv
初始化嵌入Portal的环境
Public Function CreateFormEnv(ByVal sKey As String, ByRef formObj As Object) As VBFormDescriptor
sKey: Key,注意不能是form的Hwnd,在窗体的生命周期中,此值必须唯一; formObj: Form对象
3.3.3 CloseForm
关闭一个已经打开的窗体
Public Function CloseForm(ByVal sKey As String, ByVal obj As Object)
sKey: Key,注意不能是form的Hwnd,在窗体的生命周期中,此值必须唯一
obj: Form对象。
3.3.4 FormIsOpened
判断某个Key值的窗体是否已经打开
Public Function FormIsOpened(ByVal sKey As String)
sKey: Key,注意不能是form的Hwnd,在窗体的生命周期中,此值必须唯一;
3.3.5 CreatePortalToolbarTag
创建Toolbar的Tag信息
Public Function CreatePortalToolbarTag(Image As String, actionSet As String, toolbarType As String) As String
Image按钮的图片 actionSet分组
toolbarType分组Toolbar的类型
3.3.6 SetFormActive
使某个窗口成为当前窗口
Public Function SetFormActive(ByVal sKey As String, ByVal obj As Object) sKey: Key,注意不能是form的Hwnd,在窗体的生命周期中,此值必须唯一 obj: Form对象
3.4挂接菜单
如果是文件夹这里选否 自动生成。 这里选择VB DLL 菜单的多语名称,将在U8左树菜单里显VB DLL时,此项无效。 输入VB DLL 的完整类名称。
4. 如何开发可与门户集成的.NET User Control
.net user control与门户集成需要建立实现INetUserControl接口的组件
4.1通过vs.net建立一个项目类型为类库的项目
此处项目名称为UFIDA.U8.Portal.NetProductSample
4.2继承门户中类NetLoginable
在该项目中添加以下DLL的引用 Windows.Form.dll
U8安装路径\\Framework\\UFSoft.U8.Framework.Login.UI.dll U8安装路径\\Interop\\Interop.U8Login.dll
U8安装路径\\Interop\\ Interop.UFPortalProxyInterface.dll U8安装路径\\Portal\\UFIDA.U8.Portal.Framework.dll U8安装路径\\Portal\\UFIDA.U8.Portal.Proxy.dll
U8安装路径\\Portal\\UFIDA.U8.Portal.Common.dll
在项目中新建一个类,该类需要继承类NetLoginable,并重写其中的两个方法,示例如下: public override object CallFunction(string cMenuId, string cMenuName, string cAuthId, string cCmdLine) {
INetUserControl mycontrol = new MyNetUserControl(); mycontrol.Title = \;
base.ShowEmbedControl(mycontrol, cMenuId, true); return null; }
public override bool SubSysLogin() {
Return true; }
4.3 实现接口INetUserControl
在项目中再新建一个类,该类实现接口INetUserControl,INetUserControl接口有三个属性(EditorPart、EditorInput、Title)和三个方法(CreatControl、CreatToolbar、CloseEvent),详细说明:
4.3.1 EditorPart
属性原型声明:NetEditor EditorPart { get;set;} 对于二次开发人员 ,这个是只读属性,严禁为该属性赋值。 通过这个属性,二次开发人员可以访问UAP表单在门户中显示的页签对象,可以执行页签关闭等操作。
4.3.2 EditorInput
属性原型声明:NetFormInput EditorInput { get;set;}
对于二次开发人员 ,这个是只读属性,严禁为该属性赋值。 通过这个属性,二次开发人员可以访问门户工具栏上的按钮。
4.3.3 Title
属性原型声明:string Title{ get;set;}
对于二次开发人员 ,可以设置这个属性,设置该属性后,属性值即打开单据后相应的页签标题。
4.3.4 CreateControl
方法原型: ///
/// 创建UserControl对象 ///
/// ///
/// ///
System.Windows.Forms.Control CreateControl(U8Login.clsLogin login, string MenuID, string Paramters);
功能描述: 该方法创建要显示的usercontrol
参数描述: login u8登陆对象,该对象不能转换成u8Login.clsLoginClass. MenuID: 打开的菜单ID
Paramters 菜单的参数描述,它是一个XML字符串 其定义格式如下:
dllpath:dll的路径,要用u8soft的相对路径,最好放在uap目录下; id:UserContrl唯一标识,其值自定;
type:属性值必须为\,区分大小写;
parameters:需要给程序(UserControl)传送的数据,格式自定。 返回值 要显示的usercontrol 用法:
要在门户中显示自定义的窗体,必须在此函数内实例化一个从control继承过来的对象 ,并且返回该对象
4.3.5CreateToolbar
方法原型: ///
/// 创建toolbar对象 ///
///
VoucherAction[] CreateToolbar(U8Login.clsLogin login); 功能描述:在u8门户上创建Toolbar对象 参数描述: login 当前的u8登陆对象 返回值 toolbar对象数组
VoucherAction对象是一个toolbar button的描述其用法如下 其参数描述如下:public VoucherAction(string text, string toolTip, bool isSystemButton, bool isHavePopedom, string id, IActionDelegate dele, VoucherActionType typeName, int sortNo, string parentKey, string authID);
Text:button的名称 toolTip:提示名称
isSystemButton:是否系统按钮
isHavePopedom:是否需要权限控制
id:toobar button的ID,该ID不允许重复,如果重复则后添加的对象无效 dele:action的代理对象,在该代理内实现toolbar的具体操作
typeName: toolbar button共分四种类型,类型相同的toolbar button显示在同一组中 sortNo:排序号
parentKey:父键,如果没有则为null authID:权限ID 用法:
//定义toolbar返回对象
UFIDA.U8.Portal.UAPFacade.VoucherAction[] actions = new VoucherAction[2]; //定义toolbar的处理事件
UserActionDelegate actionDelegate = new UserActionDelegate(); //实例化toolbar button对象
actions[0] = new VoucherAction(\确定\\false, false, \actionDelegate, VoucherActionType.Normal, 1, null, null);
actions[0] = new VoucherAction(\取消\\false, false, \actionDelegate, VoucherActionType.Normal, 1, null, null); //返回要显示的toolbar return actions;
4.3.6 CloseEvent
方法原型: ///
///
bool CloseEvent();
功能描述:usercontrol的关闭事件
参数描述: 返回值 是否关闭当前窗体,如果是true则关闭 否则保持当前状态
4.4 编译该控件输出DLL
编译出的DLL推荐拷贝到u8soft\%uap\\runtime目录下
4.5示例源程序代码
示例源程序:。
4.6 挂接菜单
如果是文件夹这里选否 这里选择Usercontrol .NET菜单的多语名称,将在U8左树菜单里显示 继承了NetLoginable类的类名称(包含命名空间)
在挂接菜单后,还需要在UFSystem库中的ua_idt表中添加一条记录,(uap已经自动添加)
insert into ua_idt (id,[assembly],catalogtype,[type],class)
values('test','.\%uap\\runtime\\UFIDA.U8.Portal.NetProductSample.dll',0,2,'UFIDA.U8.Portal.NetProductSample.MyLoginable')
为二次开发编译后的dll存放路径,是一个相对于U8安装目录的相对路径 参数不填即可。
其中:
'test'为挂架菜单的菜单编号;
'.\%uap\\runtime\\UFIDA.U8.Portal.NetProductSample.dll'为二次开发编译后的dll存放路径。
'UFIDA.U8.Portal.NetProductSample.MyLoginable'为二次开发中继承了NetLoginable类的类名称(包含命名空间)。
5. 可执行文件(EXE)如何挂接到门户
1、打开菜单调整工具;
2、鼠标选中需要挂接的文件夹(如果没有可以用菜单调整工具新建文件夹),点新增按钮;
3、
如果是文件夹这里选否 自动生成 这里选择EXE 菜单的多语名称,将在U8左树菜单里显示 EXE时,参数无效 这里输入EXE文件的路径,是一个相对于U8 安装路径的相示E:\\U8Soft\\EAI\\U8EAI.exe。 径,举例,U8安装在E:\\U8Soft,这里设置为.\\EAI\\U8EAI.exe
4、保存后,自动生成一个菜单编号,这里是UA8;
6、UAP表单和UAP列表如何挂接到门户
1、挂接UAP表单
如果是文件夹这里选否 这里选择UAP表单 输入,只能由字母和数字组成。 菜单的多语名称,将在U8左树菜单里显示 UAP表单时,此项无效。 形如 2、挂接UAP列表 如果是文件夹这里选否 输入,只能由字母和数字组成。 这里选择UAP列表 菜单的多语名称,将左树菜单里显示 UAP列表时,此项无效。 形如 7.1 相关表结构 7.1.1UA_Menu表结构 字段名 AutoID cMenu_Id cMenu_Name cMenu_Eng cSub_Id IGrade cSupMenu_Id bEndGrade cAuth_Id iOrder iImgIndex Paramters Depends Flag 数据类型 uid String String String String Int16 String Boolean String Int32 Int32 String String Int 含义 自动编号 菜单编号 菜单名称,输入 程序类型 模块标识,程序处理 级次,根据当前选中菜单程序自动处理 上级菜单编号,根据当前选中菜单程序自动处理 是否末级,输入, 功能权限编号,程序内部处理,控制权限时有效(cAuth_Id= cMenu_Id)。 显示顺序号,程序处理 图标索引号,暂不用 参数,输入,只有末级菜单才允许录入参数 依赖,暂不用 标志,暂不用 7.1.2UFMenu_Business_Lang表结构(菜单的多语表) 字段名 MenuId Caption 数据类型 含义 菜单标识,对应UA_Menu表的cMenu_Id值 菜单显示名称(简体中文名称显示的是UA_Menu表的cMenu_Name值) 语言区域 ZH-CN――简体中文 ZH-TW――繁体中文 EN-US――英文 LocaleId 注:U8的系统菜单在UFSystem库里,UAP新增或者菜单调整工具新增的菜单在UFData库里,二次开发增加的菜单也要求在UFData库里。 7.1.3 UA_IDT表结构 字段名 id assembly catalogtype 数据类型 string string int 含义 标识,一般等于ua_menu表里面的cMenu_Id 菜单对应的具体程序 分类,目前都设置为0 菜单对应的程序类型 0-VB DLL 1-EXE 2-.NET UserControl 程序类型决定了assembly和class的内容 type=2时有效,.NET UserControl中继承了NetLoginable的类 目前没有作用,设置为null 目前没有作用,设置为null 目前没有作用,设置为null 标志是否有变化 type int class string entrypoint parameter reserved ufts string string string 时间戳 7.2各种程序类型的增加方法 7.2.1 VB DLL: UA_Menu: ua_menu.cmenu_id= “UA”+顺序号 ua_menu.csub_id=null ua_menu.Paramters=null UA_Menu. cMenu_Eng=’0’ 需要ufsystem..ua_idt中增加记录: id= ua_menu.cmenu_id type = 0 assembly = dll类名 7.2.2 EXE UA_Menu: ua_menu.cmenu_id= “UA”+顺序号 ua_menu.csub_id=null ua_menu.Paramters=null UA_Menu. cMenu_Eng=’1’ 需要ufsystem..ua_idt中增加记录: id= ua_menu.cmenu_id type = 1 assembly = EXE文件路径(相对于U8安装的相对路径) 7.2.3 UAP表单 处理UAP增加的菜单无意识被删除需要手工添加,或者,需要UAP菜单挂接不同位置。 UA_Menu: ua_menu.cmenu_id= “UA”+顺序号 ua_menu.csub_id=’UA’ ua_menu.Paramters=形如 不需要在ufsystem..ua_idt中增加记录。 7.2.4 UAP列表 处理UAP增加的菜单无意识被删除需要手工添加,或者,需要UAP菜单挂接不同位置。 UA_Menu: ua_menu.cmenu_id= “UA”+顺序号 ua_menu.csub_id=’UA’ ua_menu.Paramters=形如 id=”eea90b20-4a2b-4149-8d00-820818dcd38f”/> UAPTrain_0009为表单编号;eea90b20-4a2b-4149-8d00-820818dcd38f为表单列表ID; UA_Menu. cMenu_Eng=’3’ 不需要在ufsystem..ua_idt中增加记录。 7.2.5 .Net UserControl 系统定义一个接口IUserControl,只有两个属性:U8Login对象和菜单对象(对应的菜单行数据)。如果.Net UserControl需要U8Login对象必须实现这个接口,否则可以不实现这个接口。 UA_Menu: ua_menu.cmenu_id= “UA”+顺序号 ua_menu.csub_id=’UA’ ua_menu.Paramters= property> dllpath:dll的路径,要用u8soft的相对路径,最好放在uap目录下; id:UserContrl唯一标识,其值自定; type:属性值必须为\,区分大小写; parameters:需要给程序(UserControl)传送的数据,格式自定。 UA_Menu. cMenu_Eng=’4’ 不需要在ufsystem..ua_idt中增加记录。 附录:门户示例详解 内容 :增加产品 操作窗口 写入门户消息 联查其他功能 第一步:增加产品 在UFsystem 中执行下列sql --增加门户菜单 INSERT INTO [UFSystem].[dbo].[UA_Menu]([cMenu_Id], [cMenu_Name], [cMenu_Eng], [cSub_Id], [IGrade], [cSupMenu_Id], [bEndGrade], [cAuth_Id], [iOrder], [iImgIndex], [Paramters], [Depends], [Flag]) VALUES('LZ','测试产品',null,'LZ',0,'SCMG',0,NULL,0,0,NULL,NULL,NULL) INSERT INTO [UFSystem].[dbo].[UA_Menu]([cMenu_Id], [cMenu_Name], [cMenu_Eng], [cSub_Id], [IGrade], [cSupMenu_Id], [bEndGrade], [cAuth_Id], [iOrder], [iImgIndex], [Paramters], [Depends], [Flag]) VALUES('LZ01','测试产品单据1',null,'LZ',1,'LZ',1,NULL,0,0,NULL,NULL,NULL) INSERT INTO [UFSystem].[dbo].[UA_Menu]([cMenu_Id], [cMenu_Name], [cMenu_Eng], [cSub_Id], [IGrade], [cSupMenu_Id], [bEndGrade], [cAuth_Id], [iOrder], [iImgIndex], [Paramters], [Depends], [Flag]) VALUES('LZ02','测试产品单据1列表',null,'LZ',1,'LZ',1,NULL,0,0,NULL,NULL,NULL) --增加idt对应记录 select * from ua_idt INSERT INTO [UFSystem].[dbo].[ua_idt]([id], [assembly], [catalogtype], [type], [class], [entrypoint], [parameter], [reserved]) VALUES('LZ01','TestVBActiveXDll.Person',0,0,null,null,null,null) INSERT INTO [UFSystem].[dbo].[ua_idt]([id], [assembly], [catalogtype], [type], [class], [entrypoint], [parameter], [reserved]) VALUES('LZ02','TestVBActiveXDll.Person',0,0,null,null,null,null) 效果如下 第二步:编译 编译TestVBActiveXDll.vbp 到 u8soft\%ufcomsql 目录下 第三步:打开产品 登录 u8打开测试产品单据1 效果如下 第四步:打开单据 界面包含四个部分 1、有关工具条的操作 2、有关窗口操作 3、有关消息中心 4、有关联查单据 1,2 对照代码参考即可 第五步:消息中心 要往门户发自己的消息分两个步骤 1:增加一个消息类型(如果是发现有类型的消息,则忽略该步骤) --预置一条消息类型,指定类型为notice 通知 If Not Exists (Select 1 From UFSystem..UA_MessageType where MsgTypeId = 313555) Insert Into UFSystem..UA_MessageType(MsgTypeId,MsgTypeName,HandlerName,SourceId,NeedProcess,OnlySupportBS) values(313555,'新增通知类型-test','Notice','04',1,0) go --在消息导航中增加一条记录 if not exists(select 1 from UA_NavigationNode where Name=N'313555') insert into Ufsystem..UA_NavigationNode(Name,Text,Visible,MsgTypeID,ParentNodeName) values(N'313555',N'313555',0,N'313555',N'Alarmed') GO 2:往门户发送消息,门户消息存于UA_message表中, 可以直接写表,但是不推荐 推荐调用组件写入 '向门户消息中心表中写入数据 '方式1:直接写表 '方式2:调用u8现有组件写入 Private Sub cmdSendMessageToMTC_Click() Dim objMsg As SendMsg.CSendMsg Set objMsg = CreateObject(\ '设置登录对象 Dim oLoginTmp As Object Set oLoginTmp = g_business.GetVBclsLogin() If Not objMsg.SetLogin(oLoginTmp) Then MsgBox \设置登录对象失败\ End If '调用方法 '用于联查的消息 Dim cn As New ADODB.Connection cn.ConnectionString = oLoginTmp.ufsystemdb.Name cn.Open Call objMsg.AddNotifyInfo(cn, \联查单据测试\ cn.Close Set cn = Nothing ' objMsg.Notify 'InsertMsg ' End Sub 写完消息后,门户消息中心 刷新一次 会看到刚才增加的消息 第六步:消息中心联查单据 关闭 测试单据页签,到消息中心双击刚才增加的记录 “联查单据测试” 可以看到双击后门户自动打开了测试单据001 第七步:调用其他功能,如联查其他单据 Private Sub cmdViewSaleOrder_Click() 代码如下 Call g_business.ResetCallFunctionFlag Dim strNewCommandline As String strNewCommandline = \ 销售订单 &&&SubSysID:SA&&&AuthID:SA03010104&&&CmdLine:\ Call g_business.RunCommand(strNewCommandline) End Sub