本文简要介绍了如何在K/3 Cloud V6.0版本中为WPF GUI客户端程序定制GUI登录界面插件的步骤。包括在特殊行业应用中对登录界面的定制需求,详细部署二次开发组件的过程,如安装组件、配置下载列表、启动客户端程序并下载组件,以及如何启动定制登录UI组件。同时,文章还指导了如何在Visual Studio中制作定制登录UI界面组件,包括引用必要的组件、编写实现定制化登录UI控件的桌面客户端代码,以及提供了登录后逻辑处理的示例和登录窗口弹出工具类的使用。
增加功能:定制GUI登录界面插件 (目前仅支持到WPF的GUI客户端程序) 版本:K/3 CLoud V6.0
一、应用背景
在特殊行业应用中,对登录需求有特定业务场景,需要定制一些登录特定逻辑,例如医疗系统,POS系统,B2C后台系统等等。这时候通用界面可能信息太多,需要做 适当简化,就需要用到定制登录界面UI来满足需求。
二、部署二次开发组件
1、在K/3 Cloud服务器安装目录的【WebSite/ClientBin/CustomControl/WPF】目录下部署二次开发组件,这个目录安装包会创建。自定义组件可以用Zip压缩文件压缩为Zip格式,后修改后缀名为.kdz。
2、配置组件下载列表MainDownloadList.xml
2.1、运行记事本编辑器,打开安装目录【WebSite/ClientBin/CustomControl/WPF/MainDownloadList.xml】的文件。
手工拷贝一个节点(一个文件需要一个节点进行注册如下图)。然后修改绿色的文件名为你的组件名就好了。
2.2、如果有组件需要更新,请拷贝相关组件到【WebSite/ClientBin/CustomControl/WPF】目录下,并执行上面2.1的步骤,注意更新组件的动作仅在客户端启动时运行一次。同时需要修改注册文件的版本号,以便客户端能够更新到最新组件,如下图:
3、启动K/3 Cloud客户端桌面版程序,这时程序会自动按照服务器地址设定检查组件版本,并按需要下载相关客制化组件到本地的 【%Program Files %\Kingdee\K3Cloud\DeskClient\K3CloudClient\controlplugins】目录下。
4、启动定制登录UI组件,在【%Program Files %\Kingdee\K3Cloud\WebSite\App_Data\】目录下,打开编辑Common.config,找到Appsettings节点,在该节点子节点中加入如下新节点,保存即启动插件成功:
<!--定制化登录界面-->
<add key ="CustomLoginUI" value="Kingdee.XPF.CustomControlPlugins.CustomLoginUI,Kingdee.XPF.CustomControlPlugins" />
特别注意:(千万不要修改上面的key属性,固定必须是“CustomLoginUI",value可以替换为你自己开发的控件组件,例如“LoginTest.LoginUI,LoginTest”,通用的DotNet类描述格式)
三、制作定制登录UI界面组件
1、在Visual Studio 2012中新增类库工程;需要新增有WPF界面元素的,必须新建WPF类库类型的工程。
2、引用服务器安装目录下IDE的基础组件如下(安装K/3 Cloud安装包+最新补丁,可得下面组件):
Kingdee.BOS.dll [必选],
Kingdee.BOS.Client.Core.dll [必选],
Kingdee.BOS.ServiceFacade.KDServiceClient.dll [可选],
Kingdee.BOS.ServiceFacade.KDServiceClientFx.dll [可选],
Kingdee.BOS.XPF.ControlPlugins.Contracts.dll [可选]
3、新建继承自DotNetWPF框架的UserControl(WPF)的类,编写定制化登录UI控件桌面客户端代码如下。重点实现IKDLoginControl接口。
重点关注LoginInfo GetLoginInfo()接口实现和调用 this.Owner.DoLogin()以及成功登录后调用this.Owner.LoadMainWindow()接口进入主控界面。
4、2015-11-09,6.0发布后,6.0的This.Owner接口改为IKDLoginControlOwner类型了。二开代码访问必须符合该接口类型。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Kingdee.BOS.Client.Core;
using Kingdee.BOS.Authentication;
using Kingdee.BOS.ServiceFacade.KDServiceClient.Account;
using Kingdee.BOS.ServiceFacade.KDServiceClient;
using Kingdee.BOS.DataCenterInfo;
namespace Kingdee.XPF.CustomControlPlugins
{
/// <summary>
/// Interaction logic for CustomLoginUI.xaml
/// </summary>
public partial class CustomLoginUI : UserControl ,IKDLoginControl
{
IKDLoginControlOwner Owner { get; set; }
ItemModel currentDataCenter { get; set; }
public CustomLoginUI()
{
InitializeComponent();
}
public void ClearData()
{
}
public void DoLogin()
{
}
public bool Focus(string key)
{
return true;
}
public LoginInfo GetLoginInfo()
{
var sDCName = DCName.Text;
var proxy = new AccountClientProxy();
var dt = DateTime.Now;
var dclist = proxy.GetDataCenterList();
var dcItem = dclist.Find(new Predicate<DataCenter>((dc) =>
{
return dc.Name.Equals(sDCName);
}));
this.currentDataCenter = new ItemModel()
{
ID = dcItem.Id,
Header = dcItem.Name
};
string userName = this.UserName.Text.Trim();
string userPwd = this.PWD.Text.Trim();
int lcid = 2052;
string acctID = this.currentDataCenter.ID;
var loginInfo = new LoginInfo()
{
Username = userName,
Password = userPwd,
AcctID = acctID,
Lcid = lcid,
AuthenticateType = AuthenticationType.PwdAuthentication,
ClientInfo = this.GetOwner().GetClientInfo()
};
return loginInfo;
}
public IKDLoginControlOwner GetOwner()
{
return this.Owner;
}
/// <summary>
/// 获取窗口标题信息
/// </summary>
/// <returns></returns>
public string GetFormTitle()
{
return "Customize Login UI For Third Provider.";
}
public bool IsDataLoaded()
{
return true;
}
public void LoadLocalSettings()
{
;
}
public IKDLoginControl NewInstance()
{
return new CustomLoginUI();
}
public void SaveLoginSettings()
{
;
}
public void SetOwner(IKDLoginControlOwner owner)
{
this.Owner = owner;
}
public void SetProgressTips(string tips)
{
;
}
public void UpdateGobalLocalId(string localId)
{
;
}
public void Release()
{
this.Owner = null;
}
public KDSize GetUISize()
{
return new KDSize() { Height = 500, Width = 700 };
}
private void btnDoLogin_Click(object sender, RoutedEventArgs e)
{
var sDCName = DCName.Text;
var ret = this.Owner.DoLogin();
ret.Context.DataCenterName = sDCName;
if (ret.LoginResultType == LoginResultType.Success)
{
this.Owner.LoadMainWindow();
}
else
{
this.Owner.ShowErrorMessage(new Exception(ret.Message));
}
}
}
}
四、例子
1、按照【二、部署二次开发插件】中的第4小点打开默认插件;
2、运行客户端GUI程序应用,将会看到登录界面变成如下Demo定制登录UI插件的界面(演示界面,未做任何修饰和密码处理),如下图:
五、登录后逻辑 。(2016-03-18补丁功能)
1、登陆后获取LoginResult对象,判断是否需要窗口提示,并参考2中的工具类进行使用;
2、登录窗口弹出工具类:
2.1 使用系统默认密码修改框提示密码修改
Kingdee.BOS.XPF.Component.Utils.KDLoginUtils.ShowModifyPwdWindow(this.Owner as Window, new Action(() =>{
this.pbx_Pwd.Password = "";
this.pbx_Pwd.Focus();
}));
2.2 制定自定义单据FormId密码修改框提示密码修改
var arg = new Kingdee.BOS.Client.Core.KDLoginInfoChangeArgs()
{
OldPwd = oldPwd,
UserId = userid,
FormId = pwdFormid,//自定义单据
LayoutId = layoutid//自定义单据布局ID,为空默认布局
};
Kingdee.BOS.XPF.Component.Utils.KDLoginUtils.KDLoginUtils.ShowModifyPwdWindow(arg, AfterOpenPublishForm);
2.3 制定自定义单据FormId提示相关操作
var arg = new KDLoginInfoChangeArgs()
{
FormId = formId,//自定义单据
InputData = inputData//自定义单据传入数据,格式自定义
};
Kingdee.BOS.XPF.Component.Utils.KDLoginUtils.KDLoginUtils.ShowSpecialForm(arg, AfterOpenSpecialForm);
2.4在K/3 Cloud的默认登录界面中,针对LoginResult.LoginResultType的处理如下,可以作为你的插件参考:a
switch (loginRet.LoginResultType)
{
case LoginResultType.Failure:
KDMessageBox.Show(loginRet.Message,
ResManager.LoadKDString("信息提示", "014001000000097"),
this.Owner as Window, KDMesType.Error);
this.pbx_Pwd.Focus();
return;
case LoginResultType.PWError:
KDMessageBox.Show(loginRet.Message,
ResManager.LoadKDString("信息提示", "014001000000097"),
this.Owner as Window, KDMesType.Warn);
this.pbx_Pwd.Focus();
this.pbx_Pwd.Password = "";
return;
case LoginResultType.PWInvalid_Optional:
this.pbx_Pwd.Password = "";
if (KDMessageBox.Show(loginRet.Message,
ResManager.LoadKDString("密码修改提示", "014001000000100"),
this.Owner as Window, KDMesType.Question, KDMesButtons.YesNo) == KDMesResult.Yes)
{
ShowModifyPwdWindow(oldPwd, loginRet.Context == null ? "" : loginRet.Context.UserId.ToString());
return;
}
break;
case LoginResultType.PWInvalid_Required:
this.pbx_Pwd.Password = "";
KDMessageBox.Show(loginRet.Message,
ResManager.LoadKDString("密码修改提示", "014001000000100"),
this.Owner as Window, KDMesType.Warn);
ShowModifyPwdWindow(oldPwd, loginRet.Context == null ? "" : loginRet.Context.UserId.ToString());
return;
case LoginResultType.Activation:
ShowModifyPwdWindow(oldPwd, loginRet.Context == null ? "" : loginRet.Context.UserId.ToString(), "SEC_SetPwd");
return;
case LoginResultType.Wanning:
KDMessageBox.Show(loginRet.Message,
ResManager.LoadKDString("警告提示", "014001000001548"),
this.Owner as Window, KDMesType.Warn, KDMesButtons.Ok);
break;
case LoginResultType.DealWithForm:
if (string.IsNullOrWhiteSpace(loginRet.FormId)) break;
ShowSpecialForm(loginRet.FormId, loginRet.FormInputObject);
return;
default:
break;
}
3、在工具类显示指定表单后,在该表单的业务插件中编写自己的业务逻辑。
传入数据在业务插件中提取:
var custArgs = this.View.OpenParameter.GetCustomParameter("inputData");
六、web端的定制登录方案
1、制作定制登录网页;
2、制作定制登录逻辑实现免登录服务端插件,参考:【利用启动插件校验机制实现免登录功能,实现跨系统无缝集成】链接地址: https://vip.kingdee.com/article/25013;
3、在定制登录网页登录后实现免登跳转;
推荐阅读