Views: 83
我們目標是寫一支DLL,在申請者送出後讀取表單資料,然後將資料存到資料表Z_TRIGGER_TEST
。
Trigger用途
在BPM模組中,我們如果需要這幾樣功能,透過Trigger比較容易,這功能其實是所謂的hook,但在UOF2稱為TRIGGER
- 申請者送出表單時取到電子表單的內容並寫到特定的資料表
- 申請者送出將表單內容送去外部系統
- 在流程中將欄位填入特定資料,例如將評比分數轉換為ABC
前置準備
- 先把UOF2安裝好,我安裝到
C:\Web\UOFTEST\
,這篇教學使用的是v28版,官方2025公班導入時提供的版本 - 創好一個帳號(不建議用admin),然後可以設定為系統管理員
- Visual Studio 2022,我使用的是社群版本
Getting Start
創立專案
VISUAL STUDIO 2022 > 新增 類別庫專案(.Net Framwork) 英文版是Class Library(.NET Framwork)
這邊要注意要選有(.NET Framwork的),然後.Net Framework版本要選4.8
創好之後刪除Class1.cs
加入必要的參考元件

選擇 瀏覽Browse > Browse..瀏覽,接著找到網站的bin
資料夾,我的是C:\WEB\UOFTEST\bin
,然後直接貼底下列出的黨名
(印象中這是公班導入時老師建議的常用DLL)
Quartz.dll
排程有關的Ede.Uof.EIP.Organization.dll
組織有關的Ede.Uof.EIP.Organization.Util.dll
組織有關的Ede.Uof.EIP.Plant.dll
設備借用有關的Ede.Uof.EIP.ResourceLibrary.dll
Ede.Uof.EIP.Schedule.CalendarSync.dll
行事曆有關的Ede.Uof.EIP.Schedule.Common.dll
行事曆有關的Ede.Uof.EIP.Schedule.Corporation.dll
行事曆有關的Ede.Uof.EIP.Schedule.dll
行事曆有關的Ede.Uof.EIP.Schedule.Report.dll
行事曆有關的Ede.Uof.EIP.SystemInfo.dll
Ede.Uof.Utility.Data.dll
Ede.Uof.Utility.dll
大部分重要的函數都在這邊Ede.Uof.Utility.Log.dll
Ede.Uof.Utility.Message.dll
寄信有關Ede.Uof.Utility.Page.Common.dll
頁面元件有關Ede.Uof.Utility.Page.dll
Ede.Uof.Utility.Task.dll
排程有關Ede.Uof.WKF.Design.dll
電子表單有關Ede.Uof.WKF.dll
電子表單有關Newtonsoft.Json.dll
物件轉JSON有關
加完後按下OK
加入後可以在參考(Reference看到)
表單簽核事件
一等一UOF2的表單總共有幾個事件
- 起單
- 簽核
- 結案
- 取回
- 作廢
- 變更狀態(表單管理員)
比較常用的是前三個狀態
設計一個TRIGGER測試表單
表單名稱:測試TRIGGER
表單設定
通常我不勾「預設儲存副本」,跟不勾「下一站若為相同簽核者則跳過」
設計表單
我們一開始欄位不用多,只需幾個代表性欄位
- 表單編號(
DOC_NBR
) - 申請者(
APPLICICATE
) - 申請者部門(
APPLICICATE_DEPT
) - 單行文字(
SINGLE_TEXT
) - 申請日期(
APPLY_DATE
)
加入流程
設計完成後加入流程,這邊測試上就加入兩個申請者就好。
發佈表單
TRIGGER命名
- 單一
Trigger
:如果沒有要把起單、簽核、結案等表單不同階段分開為不同triiger,這邊直接用Trigger
就好。 - 多個
Trigger
:起單、簽核、結案等表單不同階段分開為不同Trigger- 起單:
TriggerStart
- 簽核:
TriggerSign
- 結案:
TriggerFinish
- 作廢:
TriggerCancel
- 退回:
TriggerReturn
- 起單:
常用的是這五種
開始寫TRIGGER
我們目標是讀取表單資料,然後將資料存到資料表Z_TRIGGER_TEST
。
新增 Trigger.cs
對專案按下Add之後選Class後,輸入Trigger.cs
這邊要做幾件事
- 可見度改為
public
- 繼承兩個介面
ICallbackTriggerPlugin
- 加入
using Ede.Uof.WKF.ExternalUtility;
,這個通常會自動加入,如果沒加入的話自己加一下,如果Visual Studio顯示找不到的話,應該是沒將對應的dll加入參考,請補一下。
實做Trigger介面
這邊Visual Studio
有自動實做的功能,先將滑鼠移到1紅線處,接著點出來的2小圖,然後選3 implement interface
實做後我們要先把 throw
都刪除,然後在GetFormResult()
加入一個Return "" ;
改完之後如圖。
之後我們目標在GetFormResult()
,其他兩個方法不用理會
取得表單XML內容
表單送出後會存入XML,要取得的話有兩個方法
- 從資料庫的
TB_WKF_TASK
資料表用表單編號查詢 - 從
applyTask
取得表單的內容
從資料庫取得
表單的最後狀態在UOF2系統中是儲存在資料表TB_WKF_TASK
,可以透過SQL查詢取得,不過我寫Trigger不太用這個方式。
SELECT TOP (1) [CURRENT_DOC] FROM [dbo].[TB_WKF_TASK] WHERE [DOC_NBR] = '表單編號'
從applyTask取得
寫法關鍵在於 透過applyTask.CurrentDocXML
可以拿到XML的內容,然後通常我會存到硬碟中,整個寫起來作法如下。
using Ede.Uof.Utility.Data;
using Ede.Uof.WKF.ExternalUtility;
using System;
using System.Xml;
namespace UOF_DEV
{
public class Trigger : ICallbackTriggerPlugin
{
public void Finally()
{
}
public string GetFormResult(ApplyTask applyTask)
{
//取得表單編號
string DOC_NBR = applyTask.FormNumber;
//將目前表單內容讀到 doc物件當中
XmlDocument doc = new XmlDocument();
doc.LoadXml(applyTask.CurrentDocXML);
//儲存表單xml內容到硬碟中
doc.Save($"C:\\UOF_DEBUG\\{DOC_NBR}{DateTime.Now:yyyy-MM-dd-hh-mm-ss}.xml");
//故意失敗,用於重複測試使用
throw new Exception("For TEST");
return "";
}
public void OnError(Exception errorException)
{
}
}
}
Trigger的部分我們先寫到這,先來讓系統可以自動呼叫Trigger,這邊我多加了一個故意讓方法失敗的Exception,這是個開發上的小技巧,有了這個就能透過重送功能直接測試Trigger。
建立UOF_DEBUG資料夾
我將XML將資料儲存到C:\UOF_DEBUG
資料夾中,這個資料夾要先手動建立+賦予帳號iis apppool\應用程式集區名稱
寫入權限
設定編譯路徑
我通常設定編譯後直接送至bin
資料夾。
對專案按下右鍵,選擇屬性Properties
這邊直接從檔案總管複製路徑,貼到Output path就好,完成後儲存與關閉。
測試編譯
測試編譯UOF_DEV,對專案按下滑鼠右鍵,選擇Build(建置)
編譯後應該可以在bin
資料夾中看到跟專案同名的dll
檔案
外部組件註冊-註冊DLL
- 分類:我有先建立一個TEST的分類,這邊就看需求去規劃你的分類
- 外部組件名稱:這個不是檔名,通常是取表單名稱+事件名稱,例如
表單AA-起單
、表單AA-簽核中
、表單AA-結案
等,這邊用於之後表單事件的選擇辨認DLL用途。 - DLL:名稱,這邊要帶入DLL檔名,但不需要副檔名
.dll
- 組件路徑:namespace+class名稱,通常是專案名稱+類別名稱,所以在這邊我填入
UOF_DEV.Trigger
這邊KEY好之後按下「確定」,存檔離開。
設定表單事件要呼叫的Trigger
同樣轉到表單設計
選擇表單 > 維護表單
接著在這幾個項目選擇剛剛的組件,選好了之後按下確定。
測試送單
換個帳號(不要用admin
)
電子簽核 >>表單申請
選擇表單>>填寫表單
將一般帳號加入系統管理員
通常在本機開發時測試表單我都會用一般帳號測試,但會將這個一般帳號設定為系統管理員,不熟一等一科技EIP的朋友也別擔心,步驟如下
先用admin
帳號登入,預設密碼為123456
系統管理>管理員設定
選系統管理員 > 選取人員 之後選擇你的帳號就能新增
觀看DLL呼叫情形
這個功能需要系統管理員才看的到
電子簽核 >> 呼叫DLL狀態查詢
接著點表單 > 查詢,如果正常的話可以看見一個傳送失敗 or (傳送成功),如果都沒看到的話要到表單設計>維護表單>進階設定看DLL那邊設定有沒有選。
接著滑鼠點表單編號,可以看到傳送狀態
點進去後應該可以看見程式末端拋出來的Exception
For TEST,這代表之前到這個步驟你應該都做成功了。
拆解XML
XML我們已經透過trigger另存成一個檔案,可以在檔案總管找到它,我的是存在C:\UOF_DEBUG\
,這邊的小技巧是可以讓檔案照時間排序。
接著使用notepad++開啟檔案內容
這邊你可以發現資料大致上是這樣
fildId =
欄位名稱feildValue
= 欄位內容realValue
= 另一種欄位內容 ,人員組織多半這樣放
寫Model
我習慣靠 Dapper
這類 ORM 替代 ADO.NET
(傳統的 .NET 資料庫讀寫套件),寫得比較快而且比較不會出錯。
我們先把對應的 Model
寫出來,用途是我們寫一個物件,物件的屬性就是對應資料庫欄位,這樣靠 Dapper
寫資料庫 CRUD 時候就能自動幫我們進行對應,減少要寫的程式碼。
整理一下欄位(這個案例中都是string
)
DOC_NBR
表單編號APPLICICATE
申請者APPLICICATE_DEPT
申請者部門APPLY_DATE
申請日期,這個用DateTime
類型SINGLE_TEXT
單行文字
另外還有兩個狀態欄位建議加上去(都是string
)
TASK_STATUS
表單工作狀態:1
處理中,2
結案,3
異常,4
退回TASK_RESULT
表單申請結果:0
核准,1
否決,2
作廢,NULL
簽核中
資料表在這邊我取名為 Z_TEST_TRIGGER
,因此新增一個類別檔案 Z_TEST_TRIGGER.cs
Z_TEST_TRIGGER.cs
內容如下:
using System;
namespace UOF_DEV
{
/// <summary>
/// 測試用的表單 對應資料表 Z_TEST_TRIGGER
/// </summary>
public class Z_TEST_TRIGGER
{
/// <summary>
/// 表單編號
/// </summary>
public string DOC_NBR { get; set; }
/// <summary>
/// 申請人
/// </summary>
public string APPLICICATE { get; set; }
/// <summary>
/// 申請者部門
/// </summary>
public string APPLICICATE_DEPT { get; set; }
/// <summary>
/// 申請日期
/// </summary>
public DateTime APPLY_DATE { get; set; }
/// <summary>
/// 單行文字測試
/// </summary>
public string SINGLE_TEXT { get; set; }
/// <summary>
/// 表單工作狀態: 1處理中, 2結案, 3異常, 4退回
/// </summary>
public string TASK_STATUS { get; set; }
/// <summary>
/// 表單申請結果: 0核准, 1否決, 2作廢, NULL簽核中
/// </summary>
public string TASK_RESULT { get; set; }
}
}
接著在資料庫新增資料表,這邊我使用SSMS的介面操作
這邊依照需求寫資料,注意記得將DOC_NBR
設定為PK(主鍵)
一些處理的函數
(這邊其實靠ChatGPT就好)
我在這裡提供幾個方便的函數,可以學我將這些寫成Trigger共用DLL,但先這樣用
GetFieldValue
取得XML中FieldValue的值TryParseDateTime
字串轉DateTimeGetFormTaskStatus
將表單狀態轉為數字GetFormTaskResult
將申請結果轉為數字
/// <summary>
/// 取出XML字串的值
/// </summary>
/// <param name="doc"></param>
// <param name="fieldId"></param>
/// <returns></returns>
private string GetFieldValue(XmlDocument doc, string fieldId)
{
return doc.SelectSingleNode($"//FieldItem[@fieldId='{fieldId}']")?.Attributes["fieldValue"]?.Value;
}
/// <summary>
/// 字串轉DateTime
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private DateTime? TryParseDateTime(string value)
{
if (DateTime.TryParse(value, out DateTime result))
return result;
return null;
}
/// <summary>
///表單狀態
/// </summary>
/// <param name="applyTask">
/// </param>
/// <returns>
/// 1 = 處理中
/// 2 = 結案
/// 3 = 異常
/// 4 = 退回
/// </returns>
public static string GetFormTaskStatus(ApplyTask applyTask)
{
try
{
// 結案
// 如果 TaskStatus 不是 Active,返回 "2結案"
if (applyTask.Task.TaskStatus != ActiveStatus.Active)
{
return "2";
}
//退回申請者
// 檢查 SignResult 為 ReturnToAppliant 退回申請者 且 TaskStatus 為 Active,返回 "4退回"
if (applyTask.SignResult == SignResult.ReturnToAppliant &&
applyTask.Task.TaskStatus == ActiveStatus.Active)
{
return "4";
}
// 退回某人
// 檢查 SignResult 為 Return 且 TaskStatus 為 Active,返回 "1處理中"
if (applyTask.SignResult == SignResult.Return && applyTask.Task.TaskStatus == ActiveStatus.Active)
{
return "1";
}
// 檢查 SignResult 為 GetBack 且 TaskStatus 為 Active,返回 "4退回"
if (applyTask.SignResult == SignResult.GetBack && applyTask.Task.TaskStatus == ActiveStatus.Active)
{
return "4";
}
// 檢查 SignResult 為 Approve 且 TaskStatus 為 ReturnToApplicant,返回 "1處理中"
if (applyTask.SignResult == SignResult.Approve &&
applyTask.Task.TaskStatus == ActiveStatus.ReturnToApplicant)
{
return "1";
}
// 檢查 SignResult 為 Disapprove 且 TaskStatus 為 Active,返回 "2結案"
if (applyTask.SignResult == SignResult.Disapprove && applyTask.Task.TaskStatus == ActiveStatus.Active)
{
return "2";
}
// 如果沒有匹配條件,返回 "1處理中"
return "1";
}
catch
{
// 如果發生異常,返回 "3異常"
return "3";
}
}
/// <summary>
/// 取得表單的申請結果
/// </summary>
/// <param name="applyTask">The apply task.</param>
/// <returns>0核准, 1否決, 2作廢,3退回, NULL 簽核中</returns>
public static string GetFormTaskResult(ApplyTask applyTask)
{
return applyTask.FormResult == ApplyResult.UnKnow ? null : ((int)applyTask.FormResult).ToString();
}
將XML轉為MODEL
var model = new Z_TEST_TRIGGER
{
DOC_NBR = GetFieldValue(doc, "DOC_NBR"),
APPLICICATE = GetFieldValue(doc, "APPLICICATE"),
APPLICICATE_DEPT = GetFieldValue(doc, "APPLICICATE_DEPT"),
APPLY_DATE = TryParseDateTime(GetFieldValue(doc, "APPLY_DATE")) ?? DateTime.Now,
SINGLE_TEXT = GetFieldValue(doc, "SINGLE_TEXT"),
TASK_STATUS = GetFormTaskStatus(applyTask),
TASK_RESULT = GetFormTaskResult(applyTask)
};
安裝dapper
對專案案右鍵 然後選Manage NuGet Packages
(管理Nuget套件)

Browse 瀏覽 > 搜尋 dapper > install
Apply (套用)
⚠️ System.Runtime.CompilerServices.Unsafe 4.5.3 這邊有個坑
⚠️⚠️⚠️安裝時候會裝上舊版的System.Runtime.CompilerServices.Unsafe 4.5.3
編譯時候會蓋掉eip自帶的,導致eip變成錯誤500
裝完之後要再去Nuget的Update將System.Runtime.CompilerService.Unsafe 4.5.3 升級到 System.Runtime.CompilerService.Unsafe 5.0之後的版本,eip才能正常運作
簡單的做法就是直接全部更新就好
這樣就安裝起來了,佈署的時候要記得將 dapper.dll
一起拷貝上去,其他dapper需要的dll在eip上都新版的,所以可以不用複製
寫新增與更新
取得EIP的連線字串
_connectionString = new DatabaseHelper().Command.Connection.ConnectionString;
using Ede.Uof.Utility.Data;
using Ede.Uof.WKF.Engine;
using Ede.Uof.WKF.ExternalUtility;
using System;
using System.Data.SqlClient;
using System.Xml;
using Dapper;
namespace UOF_DEV
{
public class Trigger : ICallbackTriggerPlugin
{
/// <summary>
/// 連線字串
/// </summary>
private string _connectionString;
/// <summary>
/// 建構子
/// </summary>
public Trigger()
{
//EIP內建抓取得連線字串
_connectionString = new DatabaseHelper().Command.Connection.ConnectionString;
}
/*其他程式碼 ....*/
}
}
這邊偷懶一下,我只寫刪除+新增
/// <summary>
/// 新增或更新資料到 Z_TEST_TRIGGER 資料表
/// </summary>
/// <param name="model"></param>
public void Insert(Z_TEST_TRIGGER model)
{
string sql = @"
DELETE FROM Z_TEST_TRIGGER WHERE DOC_NBR = @DOC_NBR;
INSERT INTO Z_TEST_TRIGGER (DOC_NBR, APPLICICATE, APPLICICATE_DEPT, APPLY_DATE, SINGLE_TEXT, TASK_STATUS, TASK_RESULT)
VALUES (@DOC_NBR, @APPLICICATE, @APPLICICATE_DEPT, @APPLY_DATE, @SINGLE_TEXT, @TASK_STATUS, @TASK_RESULT)";
//將資料寫入資料庫
using (var conn = new SqlConnection(_connectionString))
{
conn.Open();
var transaction = conn.BeginTransaction();
try
{
conn.Execute(sql, model , transaction);
transaction.Commit();
}
catch (Exception)
{
transaction.Rollback();
throw;
}
}
}
完整的Trigger程式如下
using Ede.Uof.Utility.Data;
using Ede.Uof.WKF.Engine;
using Ede.Uof.WKF.ExternalUtility;
using System;
using System.Data.SqlClient;
using System.Xml;
using Dapper;
namespace UOF_DEV
{
public class Trigger : ICallbackTriggerPlugin
{
/// <summary>
/// 連線字串
/// </summary>
private string _connectionString;
/// <summary>
/// 建構子
/// </summary>
public Trigger()
{
//EIP內建抓取得連線字串
_connectionString = new DatabaseHelper().Command.Connection.ConnectionString;
}
public void Finally()
{
}
public string GetFormResult(ApplyTask applyTask)
{
//取得表單編號
string DOC_NBR = applyTask.FormNumber;
//將目前表單內容讀到 doc物件當中
XmlDocument doc = new XmlDocument();
doc.LoadXml(applyTask.CurrentDocXML);
//建立儲存表單的目錄
System.IO.Directory.CreateDirectory("C:\\UOF_DEBUG\\");
//儲存表單xml內容到硬碟中
doc.Save($"C:\\UOF_DEBUG\\{DOC_NBR}{DateTime.Now:yyyy-MM-dd-hh-mm-ss}.xml");
/*XML SAMPLE
<Form formVersionId="09a27207-17b7-4ff5-be49-3b8d2d1552a7">
<FormFieldValue>
<FieldItem fieldId="DOC_NBR" fieldValue="BPM250800001" realValue="" enableSearch="True" />
<FieldItem fieldId="APPLICICATE" fieldValue="WISH(wish)" realValue="<UserSet><Element type='user'> <userId>084ecfd9-b65a-4b99-b649-d4abcf03112c</userId></Element></UserSet>
" enableSearch="True" />
<FieldItem fieldId="APPLICICATE_DEPT" fieldValue="RD-T1" realValue="2c3feec0-c47e-b3d2-9b62-053be7cac613,RD-T1,False" enableSearch="True" />
<FieldItem fieldId="APPLY_DATE" fieldValue="2025/08/05" realValue="" enableSearch="True" fillerName="WISH" fillerUserGuid="084ecfd9-b65a-4b99-b649-d4abcf03112c" fillerAccount="wish" fillSiteId="" />
<FieldItem fieldId="SINGLE_TEXT" fieldValue="123456" realValue="" enableSearch="True" fillerName="WISH" fillerUserGuid="084ecfd9-b65a-4b99-b649-d4abcf03112c" fillerAccount="wish" fillSiteId="" />
</FormFieldValue>
</Form>
*/
var model = new Z_TEST_TRIGGER
{
DOC_NBR = GetFieldValue(doc, "DOC_NBR"),
APPLICICATE = GetFieldValue(doc, "APPLICICATE"),
APPLICICATE_DEPT = GetFieldValue(doc, "APPLICICATE_DEPT"),
APPLY_DATE = TryParseDateTime(GetFieldValue(doc, "APPLY_DATE")) ?? DateTime.Now,
SINGLE_TEXT = GetFieldValue(doc, "SINGLE_TEXT"),
TASK_STATUS = GetFormTaskStatus(applyTask),
TASK_RESULT = GetFormTaskResult(applyTask)
};
Insert(model);
//故意失敗,用於重複測試使用
throw new Exception("For TEST");
return "";
}
/// <summary>
/// 新增或更新資料到 Z_TEST_TRIGGER 資料表
/// </summary>
/// <param name="model"></param>
public void Insert(Z_TEST_TRIGGER model)
{
string sql = @"
DELETE FROM Z_TEST_TRIGGER WHERE DOC_NBR = @DOC_NBR;
INSERT INTO Z_TEST_TRIGGER (DOC_NBR, APPLICICATE, APPLICICATE_DEPT, APPLY_DATE, SINGLE_TEXT, TASK_STATUS, TASK_RESULT)
VALUES (@DOC_NBR, @APPLICICATE, @APPLICICATE_DEPT, @APPLY_DATE, @SINGLE_TEXT, @TASK_STATUS, @TASK_RESULT)";
//將資料寫入資料庫
using (var conn = new SqlConnection(_connectionString))
{
conn.Open();
var transaction = conn.BeginTransaction();
try
{
conn.Execute(sql, model , transaction);
transaction.Commit();
}
catch (Exception)
{
transaction.Rollback();
throw;
}
}
}
public void OnError(Exception errorException)
{
}
/// <summary>
/// 取得BPM表單中 FieldValue 的內容
/// </summary>
/// <param name="doc"></param>
/// <param name="fieldId"></param>
/// <returns></returns>
private string GetFieldValue(XmlDocument doc, string fieldId)
{
return doc.SelectSingleNode($"//FieldItem[@fieldId='{fieldId}']")?.Attributes["fieldValue"]?.Value;
}
/// <summary>
/// 取得BPM表單中 RealValue 的內容
/// </summary>
/// <param name="doc">表單XML</param>
/// <param name="fieldId">欄位名稱</param>
/// <returns></returns>
private string GerRealValue(XmlDocument doc, string fieldId)
{
return doc.SelectSingleNode($"//FieldItem[@fieldId='{fieldId}']")?.Attributes["realValue"]?.Value;
}
/// <summary>
/// 字串轉DateTime
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private DateTime? TryParseDateTime(string value)
{
if (DateTime.TryParse(value, out DateTime result))
return result;
return null;
}
/// <summary>
///表單狀態
/// </summary>
/// <param name="applyTask">
/// </param>
/// <returns>
/// 1 = 處理中
/// 2 = 結案
/// 3 = 異常
/// 4 = 退回
/// </returns>
public static string GetFormTaskStatus(ApplyTask applyTask)
{
try
{
// 結案
// 如果 TaskStatus 不是 Active,返回 "2結案"
if (applyTask.Task.TaskStatus != ActiveStatus.Active)
{
return "2";
}
//退回申請者
// 檢查 SignResult 為 ReturnToAppliant 退回申請者 且 TaskStatus 為 Active,返回 "4退回"
if (applyTask.SignResult == SignResult.ReturnToAppliant &&
applyTask.Task.TaskStatus == ActiveStatus.Active)
{
return "4";
}
// 退回某人
// 檢查 SignResult 為 Return 且 TaskStatus 為 Active,返回 "1處理中"
if (applyTask.SignResult == SignResult.Return && applyTask.Task.TaskStatus == ActiveStatus.Active)
{
return "1";
}
// 檢查 SignResult 為 GetBack 且 TaskStatus 為 Active,返回 "4退回"
if (applyTask.SignResult == SignResult.GetBack && applyTask.Task.TaskStatus == ActiveStatus.Active)
{
return "4";
}
// 檢查 SignResult 為 Approve 且 TaskStatus 為 ReturnToApplicant,返回 "1處理中"
if (applyTask.SignResult == SignResult.Approve &&
applyTask.Task.TaskStatus == ActiveStatus.ReturnToApplicant)
{
return "1";
}
// 檢查 SignResult 為 Disapprove 且 TaskStatus 為 Active,返回 "2結案"
if (applyTask.SignResult == SignResult.Disapprove && applyTask.Task.TaskStatus == ActiveStatus.Active)
{
return "2";
}
// 如果沒有匹配條件,返回 "1處理中"
return "1";
}
catch
{
// 如果發生異常,返回 "3異常"
return "3";
}
}
/// <summary>
/// 取得表單的申請結果
/// </summary>
/// <param name="applyTask">The apply task.</param>
/// <returns>0核准, 1否決, 2作廢,3退回, NULL 簽核中</returns>
public static string GetFormTaskResult(ApplyTask applyTask)
{
return applyTask.FormResult == ApplyResult.UnKnow ? null : ((int)applyTask.FormResult).ToString();
}
}
}
好了就可以編譯+進行重送表單到Trigger
重送表單到Trigger測試
因為之前有拋出Exception,所以可以一直重新執行,這個上線前記得拿掉。
編譯新版的後,重新回到EIP內的電子簽核>>管理>>呼叫DLL狀態查詢
選擇表單>>勾選>>重新執行>>點表單編號進去看結果
從資料庫驗證結果
寫程式的一個很重要的點 ,一定要驗證
上測試環境前的準備
- 多測試幾次,使用不同帳號跟職位進行測試
- 將儲存xml等臨時性的程式碼刪除或註解
- 進行重構:補齊註解+重新命名變數讓程式更好維護
官方文件參考
這部分如果想參考可以看 U-OfficeForce26.0系統開發手冊(電子簽核).docx.pdf
,看肆、表單事件處理
,不過我覺得寫的很少,多數技巧是我自己摸出來的。

0 Comments