Views: 1
如果要做很複雜的簽核流程,就只能靠應用程式站點了,應用程式站點有個限制不能模擬流程。
準備工作-建立測試帳號
我先建立一些測試帳號
大致上就是A-H
建立測試表單
(略)
DLL參考
主要要參考網站bin資料夾下
Ede.Uof.WKF.dllEde.Uof.WKF.Design.dll
開始寫程式
專案同樣是要用.Net 類別庫 ,版本是.Net 4.8 這個過程可以參考Trigger那邊,我這邊建立了一個類別
DemoExternal.cs 這邊依照自己需求命名寫就好
然後介面需要繼承ICallExternalDllSites
using Ede.Uof.Utility.Data;
using Ede.Uof.WKF.CustomExternal;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Xml;
namespace UOF_DEV
{
public class DemoExternal : ICallExternalDllSites
{
public void Finally()
{
}
public string GetExternalDllSites(string formInfo)
{
return "";
}
public void OnError(Exception errorException)
{
}
}
}
簡單寫寫如上
GetExternalDllSites() 的傳入資料formInfo
<ExternalFlowSite>
<!--申請資訊-->
<ApplicantInfo taskId="task代號" account="簽核帳號" formId="表單編號"
formVersionId="表單版本編號" ></ApplicantInfo>
<!--欄位結構-->
<FormFieldValue>
<FieldItem enableSearch="True" realValue=""
fieldValue="BPM200700001" fieldId="no"/>
<FieldItem enableSearch="True" realValue="" fieldValue="test"
fieldId="test1" fillSiteId="" fillerAccount="admin" fillerUserGuid="admin"
fillerName="系統管理員"/>
</FormFieldValue>
<!--站點歷程-->
<SiteHistory>
<Site siteId="" siteType="站點型態" order="0" signType="簽核型態">
<Signer account ="簽核帳號" comment="意見" signResult="簽核結果"
signTime="簽核時間!"></Signer>
</Site>
</SiteHistory>
</ExternalFlowSite>
這邊資料大致上什麼都有了
- 申請者是誰
- TASK ID
- 簽核歷程(站點歷程)
- 填寫的資料內容(欄位結構)
基本上就是從填寫的資料內容判斷要給誰
從formInfo 取XML值的範例
private string GetValue(System.Xml.XmlDocument doc)
{
//擷取 FormFieldValue
var formFieldValueNode = doc.SelectSingleNode("/ExternalFlowSite/FormFieldValue");
if (formFieldValueNode != null)
{
//在這裡可以根據表單欄位的值決定流程走向
//例如:
var fieldItemNode = formFieldValueNode.SelectSingleNode("FieldItem[@fieldId='test1']");
if (fieldItemNode != null)
{
return fieldItemNode.Attributes["fieldValue"].Value;
//後續根據 fieldValue 的值決定流程走向
//例如,如果 fieldValue 是 "test",則走簽核者A的流程;如果是 "test2",則走簽核者B的流程
}
}
return null;
}
取好該取的值之後,我們就能處理回傳流程了
回傳簽核流程
空流程
/// <summary>
/// 空的流程
/// </summary>
/// <returns></returns>
private string EmptyFlow = "<ReturnValue><EmptyFlow /></ReturnValue>";
簽核流程xml
<ReturnValue>
<Flow>
<!--第一站點-->
<!--signType:簽核型態; 0:一般;1:並簽;2:會簽-->
<Site order="0" signType="0|1|2">
<!--簽核者-->
<Signers>
<!--帳號必需要存在UOF-->
<!--方法一、僅新增帳號-->
<Signer account="簽核者帳號" />
</Signers>
<!--知會人員-->
<Alerts>
<!--帳號必需要存在UOF-->
<Alert account="知會者帳號"/>
</Alerts>
<!--自訂簽核字詞 Approve:同意,Disapprove:否決,Return:退簽-->
<CustomWords>
<Approve zh-TW="自訂字詞" zh-CN="自訂字詞" en-US="自訂字詞" />
<Disapprove zh-TW="自訂字詞" zh-CN="自訂字詞" en-US="自訂字詞" />
<Return zh-TW="自訂字詞" zh-CN="自訂字詞" en-US="自訂字詞" />
</CustomWords>
</Site>
<!--第二站點-->
<!--方法二、新增帳號、部門、職級-->
<Site order="1" signType="簽核型態">
<Signers>
<Signer account="簽核者帳號" groupId="簽核者部門" titleId="簽核者職級"/>
<Signer account="簽核者帳號" groupId="簽核者部門" titleId="簽核者職級"/>
</Signers>
<Alerts>
<Alert account="知會者帳號"/>
<Alert account="知會者帳號"/>
</Alerts>
<CustomWords>
<Approve zh-TW="自訂字詞" zh-CN="自訂字詞" en-US="自訂字詞" />
<Disapprove zh-TW="自訂字詞" zh-CN="自訂字詞" en-US="自訂字詞" />
<Return zh-TW="自訂字詞" zh-CN="自訂字詞" en-US="自訂字詞" />
</CustomWords>
</Site>
</Flow>
</ReturnValue>
這邊主要處理幾件事
- 站點
- 簽核帳號
- 知會者
- 字詞
- 簽核型態
普遍只要處理 站點順序 簽核型態 簽核者 知會者
整理流程需求
我們可以簡單的把需求整理成這樣
- 流程1
- 第一站 簽核者A B 「並簽」
- 第二站 簽核者D 知會E 「一般簽核」
- 第二站 簽核者 F G 「會簽」
簡化簽核程式
理論上可以用字串硬幹,不過也可以用物件導向的方式解決,我先把簽核的結構做成一個類別
簽核類別
/// <summary>
/// 簽核站點資訊 這邊沒處理字詞 只處理簽核者和知會者
/// </summary>
private class SiteInfo
{
/// <summary>
/// 順序 1 2 3 4
/// </summary>
public string order { get; set; }
/// <summary>
/// 0:一般;1:並簽;2:會簽
/// </summary>
public string signType { get; set; }
/// <summary>
/// 簽核人員帳號
/// </summary>
public List<string> signers { get; set; }
/// <summary>
/// 知會者帳號
/// </summary>
public List<string> alerts { get; set; }
}
將物件建立流程xml
這邊照貼就好
/// <summary>
/// 根據站點資訊列表建立流程XML
/// </summary>
/// <param name="siteInfos">站點資訊列表</param>
/// <returns></returns>
private System.Xml.XmlDocument BuildFlowXml(List<SiteInfo> siteInfos)
{
var doc = new System.Xml.XmlDocument();
XmlElement returnValue = doc.CreateElement("ReturnValue");
doc.AppendChild(returnValue);
XmlElement flow = doc.CreateElement("Flow");
returnValue.AppendChild(flow);
foreach (var siteInfo in siteInfos)
{
XmlElement site = doc.CreateElement("Site");
site.SetAttribute("order", siteInfo.order);
site.SetAttribute("signType", siteInfo.signType);
XmlElement signers = doc.CreateElement("Signers");
if (siteInfo.signers != null)
{
foreach (var signerAccount in siteInfo.signers)
{
XmlElement signer = doc.CreateElement("Signer");
signer.SetAttribute("account", signerAccount);
signers.AppendChild(signer);
}
}
site.AppendChild(signers);
XmlElement alerts = doc.CreateElement("Alerts");
if (siteInfo.alerts != null)
{
foreach (var alertAccount in siteInfo.alerts)
{
XmlElement alert = doc.CreateElement("Alert");
alert.SetAttribute("account", alertAccount);
alerts.AppendChild(alert);
}
}
site.AppendChild(alerts);
flow.AppendChild(site);
}
return doc;
}
設定簽核點
//這邊模擬簽核者
//第一站A 一般簽核
//第二站B、C 並簽 ,知會者D
//第三站F、G 會簽 知會者H
var siteInfos = new List<SiteInfo>();
//第一站:A 一般簽核
siteInfos.Add(new SiteInfo
{
order = "0",
signType = "0",
signers = new List<string> { "A" },
alerts = new List<string>()
});
//第二站:B、C 並簽,知會者D
siteInfos.Add(new SiteInfo
{
order = "1",
signType = "1",
signers = new List<string> { "B", "C" },
alerts = new List<string> { "D" }
});
//第三站:F、G 會簽,知會者H、I
siteInfos.Add(new SiteInfo
{
order = "2",
signType = "2",
signers = new List<string> { "F", "G" },
alerts = new List<string> { "H" }
});
var docSign = BuildFlowXml(siteInfos);
return docSign.OuterXml;
實際流程就看你需求兜一下,改成這樣應該好處理很多。
編譯 設定外部組件
電子簽核 > 外部組件註冊
設定簽核流程
測試送出
這邊我自己測試,沒辦法使用模擬的功能,務必要一站一站測試
完整程式碼
using Ede.Uof.Utility.Data;
using Ede.Uof.WKF.CustomExternal;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Xml;
namespace UOF_DEV
{
public class DemoExternal : ICallExternalDllSites
{
public void Finally()
{
}
public string GetExternalDllSites(string formInfo)
{
//傳入資訊
// 取得表單資訊
var doc = new System.Xml.XmlDocument();
doc.LoadXml(formInfo);
//取得TaskID
var taskId = doc.SelectSingleNode("/ExternalFlowSite/ApplicantInfo").Attributes["taskId"].Value;
//從表單內容擷取欄位值
var fieldValue = GetValue(doc);
//TODO: 從表單內容決定流程走向
//假如符合空流程的條件 回傳空流程
//if (true)
//{
// return EmptyFlow;
//}
//假如符合簽核者的條件 回傳簽核者的XML範本
if (true)
{
//這邊模擬簽核者
//第一站A 一般簽核
//第二站B、C 並簽 ,知會者D
//第三站F、G 會簽 知會者H、I
var siteInfos = new List<SiteInfo>();
//第一站:A 一般簽核
siteInfos.Add(new SiteInfo
{
order = "0",
signType = "0",
signers = new List<string> { "A" },
alerts = new List<string>()
});
//第二站:B、C 並簽,知會者D
siteInfos.Add(new SiteInfo
{
order = "1",
signType = "1",
signers = new List<string> { "B", "C" },
alerts = new List<string> { "D" }
});
//第三站:F、G 會簽,知會者H、I
siteInfos.Add(new SiteInfo
{
order = "2",
signType = "2",
signers = new List<string> { "F", "G" },
alerts = new List<string> { "H" }
});
var docSign = BuildFlowXml(siteInfos);
return docSign.OuterXml;
}
//其他情況回傳空流程
return EmptyFlow;
}
/// <summary>
/// 傳回簽核者的XML範本
/// </summary>
/// <returns></returns>
public System.Xml.XmlDocument SiteReturnTemplate()
{
string template = @"
<!--傳給電子簽核資料-->
<ReturnValue>
<Flow>
<Site order=""0"" signType=""2"">
<Signers>
</Signers>
<Alerts>
</Alerts>
</Site>
</Flow>
</ReturnValue>
";
var doc = new System.Xml.XmlDocument();
doc.LoadXml(template);
return doc;
}
/// <summary>
/// 空的流程
/// </summary>
/// <returns></returns>
private string EmptyFlow = "<ReturnValue><EmptyFlow /></ReturnValue>";
/// <summary>
/// 根據站點資訊列表建立流程XML
/// </summary>
/// <param name="siteInfos">站點資訊列表</param>
/// <returns></returns>
private System.Xml.XmlDocument BuildFlowXml(List<SiteInfo> siteInfos)
{
var doc = new System.Xml.XmlDocument();
XmlElement returnValue = doc.CreateElement("ReturnValue");
doc.AppendChild(returnValue);
XmlElement flow = doc.CreateElement("Flow");
returnValue.AppendChild(flow);
foreach (var siteInfo in siteInfos)
{
XmlElement site = doc.CreateElement("Site");
site.SetAttribute("order", siteInfo.order);
site.SetAttribute("signType", siteInfo.signType);
XmlElement signers = doc.CreateElement("Signers");
if (siteInfo.signers != null)
{
foreach (var signerAccount in siteInfo.signers)
{
XmlElement signer = doc.CreateElement("Signer");
signer.SetAttribute("account", signerAccount);
signers.AppendChild(signer);
}
}
site.AppendChild(signers);
XmlElement alerts = doc.CreateElement("Alerts");
if (siteInfo.alerts != null)
{
foreach (var alertAccount in siteInfo.alerts)
{
XmlElement alert = doc.CreateElement("Alert");
alert.SetAttribute("account", alertAccount);
alerts.AppendChild(alert);
}
}
site.AppendChild(alerts);
flow.AppendChild(site);
}
return doc;
}
private string GetValue(System.Xml.XmlDocument doc)
{
//擷取 FormFieldValue
var formFieldValueNode = doc.SelectSingleNode("/ExternalFlowSite/FormFieldValue");
if (formFieldValueNode != null)
{
//在這裡可以根據表單欄位的值決定流程走向
//例如:
var fieldItemNode = formFieldValueNode.SelectSingleNode("FieldItem[@fieldId='test1']");
if (fieldItemNode != null)
{
return fieldItemNode.Attributes["fieldValue"].Value;
//根據 fieldValue 的值決定流程走向
//例如,如果 fieldValue 是 "test",則走簽核者A的流程;如果是 "test2",則走簽核者B的流程
}
}
return null;
}
public void OnError(Exception errorException)
{
}
/// <summary>
/// 簽核站點資訊 這邊沒處理字詞 只處理簽核者和知會者
/// </summary>
private class SiteInfo
{
/// <summary>
/// 順序 1 2 3 4
/// </summary>
public string order { get; set; }
/// <summary>
/// 0:一般;1:並簽;2:會簽
/// </summary>
public string signType { get; set; }
/// <summary>
/// 簽核人員帳號
/// </summary>
public List<string> signers { get; set; }
/// <summary>
/// 知會者帳號
/// </summary>
public List<string> alerts { get; set; }
}
}
}
0 Comments