繼續昨天的FormAdapter
| 情況 | 後續動作 |
|---|---|
| 節點本身沒有任何出線(未啟用自訂決策時),或啟用自訂決策卻一個決策選項都沒有 | 直接回錯誤「FormAdapter 節點沒有出線,無法繼續」;節點連等待狀態都不會進入, 不會建立任何簽核紀錄。 |
| 未啟用自訂決策,選擇模式=單選 | 簽核者從節點本身的出線裡挑一條,往那條路徑推進。可選項目的按鈕文字:優先用該出線自己的 「標籤文字」,沒設標籤才退而使用目標節點的名稱。 |
| 未啟用自訂決策,選擇模式=複選 | 簽核者可以一次挑多條出線,同時推進多個分支(等同一個節點同時走了那幾條出線)。 |
| 啟用自訂決策,按鈕配對 1~多條出線 | 往這些出線推進;配對多條時等同一次選了多條路徑,同時往下走。 |
| 啟用自訂決策,按鈕的「流程去向」刻意不配對任何出線(target_edges 為空陣列) | 不建立任何後續節點;流程直接以 REJECTED 結束。但簽核紀錄的動作欄位是 approved 還是 rejected,看的不是按鈕語意也不是按鈕顏色,是另一條 獨立規則,見下方注意事項。 |
| 設定了簽核逾時且到期,逾時去向對應到一條有出線的路徑(純出線)或一個有配對出線的決策 | 系統自動視為簽核者選了那條路徑往下推進;fw_approval_records 新增一筆 action=timeout 的紀錄,簽核者顯示為「系統(逾時自動處理)」。 |
| 設定了簽核逾時且到期,逾時去向對應到一個 target_edges 為空的決策 | 與「按鈕刻意不配對出線」相同:流程直接以 REJECTED 結束,紀錄動作是 timeout。 |
| 簽核者解析為空清單,且簽核者類型不是 ROLE/DEPARTMENT(舊);或 ROLE/DEPARTMENT 本身解析失敗(角色、單位不存在,或「申請人本人就是 簽核者」升級到頂層仍找不到別人);找不到簽核人時=return | 不進入等待,直接以 REJECTED 結束整個流程(固定按「分離執行」模式結束,不理會 流程裡其他 End 節點的設定);action=no_assignee,簽核者顯示為 「系統(找不到簽核人)」。 |
| 同上情況,找不到簽核人時=fallback_role | 改用指定角色(全企業範圍)重新解析簽核者,正常進入等待簽核狀態;該角色當下沒有人持有也只是 繼續等,不會被判定失敗。 |
節點進入等待狀態後,能讓它繼續往下走的只有三種情況:有權限的簽核者透過表單中心送出決定;設定了簽核 逾時且已到期,由執行器排程自動喚醒重新判定;或流程因為其他分支先觸發了「結束」節點。第三種情況的後續 處理依「結束」節點的結束模式而不同——cancel 模式會主動取消所有還在等待的節點(含這個簽核 任務),任務直接從待簽清單消失,不會留下核決紀錄;detach 或 strict 模式不會 主動取消,這個任務會繼續留在簽核者的待辦清單裡,看起來完全正常——這時候如果簽核者還是把它簽了,系統照樣 會建立簽核紀錄,只是因為流程已經是終態,不會再建立任何新節點,不會報錯,也不會有任何畫面提示。詳見 結束(End)。
誰能簽,判定的不是「進關卡當下的名單快照」,而是「簽核當下即時的身分」:ROLE/ DEPARTMENT(舊)型別在簽核送出時會重新查一次角色與單位的持有關係(含代理與候補),只要 當下持有就算數,即使原本沒被列進等待中的快照也能簽;反之原本在快照裡的人若角色已被收回,就簽不了。 INITIATOR/USER/DYNAMIC 三種型別沒有這層即時判定,認的是進關卡 當下解析出的那份名單,事後身分異動不影響能不能簽。

出廠預設的SOC版流程圖,為何在設計圖中只有兩條線?其實是因為線條重疊導致視覺誤判,只要拖拉移動即可
這次特別把node拉開,避免讀者誤解。
固定寫死一個人(USER)適合「這張表單本來就該給某個特定窗口審」的情境;大多數簽核流程 更常見的需求是「依申請人的組織位置動態找主管」,這時用 ROLE 搭配 unit_scope:
{
"assignee_type": "ROLE",
"assignee_value": "<部門主管角色的 secure_code>",
"unit_scope": "APPLICANT_UNIT",
"self_target_action": "escalate_or_return"
}
unit_scope=APPLICANT_UNIT 只認「申請人自己所屬單位」持有這個角色的人;同一份設計改成 unit_scope=GLOBAL 就變成「全企業任何一個持有這個角色的人都算」,兩者是完全不同範圍,不要 互相取代。部門主管這類角色通常是「職位型」,不會因為單位是祖先關係就自動套用到上層或下層——申請人所屬 單位的上一層若也有主管,要用 unit_scope=APPLICANT_ANCESTOR(往上找)明確指定,不會因為 用了 APPLICANT_UNIT 就自動含括。self_target_action 只在申請人自己剛好就是 目標單位的主管本人時才會觸發,決定要往上一層找別人簽、還是乾脆讓本人簽、還是找不到人就退回申請人重送。
| 設定 | 行為 | 適合情境 |
|---|---|---|
| no_assignee_action=return(預設) | 直接把案件結束、記為 REJECTED,簽核者顯示「系統(找不到簽核人)」,流程不會走到 任何後續節點。 | 沒人可簽的案件不該無限期卡住;申請人可以清楚知道要重送或找人補位,是最安全的預設。 |
| no_assignee_action=fallback_role | 改派給指定角色,流程正常進入等待簽核狀態;即使改派的角色當下也沒有人持有,也只是停在等待中, 管理員之後補人即可簽,不會被判死。 | 希望案件保留、等人補位後補簽,而不是要求申請人重新走一次流程;常用來指向一個保證隨時有人持有 的全域角色(例如企業管理員)。 |
「核准」接一條出線走向正常結束;「退回補件」接到一個留痕節點後再繞回這個 FormAdapter 節點自己,形成真正的重簽迴圈——選了這個按鈕流程不會結束,會重新產生一筆等待 簽核的任務;「駁回」刻意不配對任何出線,是唯一會讓流程真的以 REJECTED 結束的按鈕。同一批 決策也可以兩個選項刻意指向同一條出線(例如「核准」與「需要補充資料」都先送到同一個下游節點),這時圖 形結構本身分不出簽核者選了哪一個,必須靠傳出變數,再交給下游的「分支」節點依變數值二次判斷。
要避免案件因為沒人簽核而卡住太久,同一個節點另外加上逾時:
"timeout_enabled": true,
"timeout_minutes": 480,
"timeout_mode": "ABSOLUTE",
"timeout_path_id": "<逾時要走的出線或決策 id>"
ABSOLUTE 從進入關卡那一刻起算,不論是否在工作時間一律倒數;WORKING 只在 簽核者的班表工作時間內倒數,適合「上班時間 8 小時內要簽完」這類需求,但簽核者沒有班表時會自動退回 ABSOLUTE,見注意事項。
顯示備註欄位關閉,但最少字數仍大於 0——簽核者永遠送不出決定
症狀:簽核畫面上根本看不到留言欄,但按下任何決策都被擋下「簽核意見至少需要 N 字」,而且 沒有辦法輸入任何文字去補足,形同卡死。
原因:關閉「顯示備註欄位」只是把留言區塊在畫面上藏起來,不會連帶把「最少字數」歸零;兩個欄位 在設定畫面上各自獨立存檔,關閉備註欄位時若沒有手動把最少字數也改回 0,儲存的設定就是 allow_comment=false 加上 min_comment_length>0 這個矛盾組合,而前端與 後端的長度檢查完全不管欄位看不看得到,只認 min_comment_length。
正確做法:要留言就同時打開「顯示備註欄位」;不需要留言就把「最少字數」設回 0。改設定後重新 打開一次面板確認兩者一致,不要只憑「我剛剛關掉了」就假設最少字數也一起清空。
角色型簽核者解析成功,但當下零持有者——不會走「找不到簽核人時」,會靜默停等
症狀:案件卡在等待簽核,待簽清單裡沒有任何人看得到這張單,也沒有觸發「找不到簽核人時」的 退回或改派,查不到任何錯誤或警告紀錄。
原因:「找不到簽核人時」的判定只在簽核者類型不是 ROLE/DEPARTMENT (舊),或這兩種類型本身解析失敗(角色、單位不存在等)時才會觸發;ROLE/ DEPARTMENT 只要角色與單位本身存在、解析「成功」,即使當下一個持有者都沒有,也會直接 帶著空的簽核者清單進入等待,不會被視為異常。
正確做法:這其實是設計上刻意允許的行為——之後只要有人被授予這個角色(或在該單位範圍內), 就能追溯簽這張已經在等待中的單,不需要事後補救。真正要避免的是「角色暫時沒人」變成事故,那應該在 角色與單位的日常管理上把關,不要指望 FormAdapter 幫忙偵測。
決策選項的「條件顯示」不會真的隱藏按鈕
症狀:在決策選項上設定了「條件顯示」(變數/運算子/比較值),存檔也沒有錯誤,但不論流程 變數是什麼值,簽核畫面上該決策按鈕永遠都在,從未被隱藏過。
原因:「條件顯示」只是把設定值存進 decision_options[].visible_when 並原樣傳給 前端,設計器與執行端都沒有任何程式碼會拿它來過濾要不要顯示這個按鈕——是一個目前沒有作用的欄位。 真正能動態隱藏決策按鈕的是另一個獨立機制:「來向變數控制」(input_variables),要設 decision_visibility 類型的控制規則,並在裡面指定要顯示哪些決策的 id。
正確做法:需要依流程變數動態隱藏/顯示某些決策按鈕時,一律改用「來向變數控制」,不要以為 在決策選項本身填了「條件顯示」就會生效。
駁回類按鈕只要接了出線,簽核紀錄一律記成「已核准」
症狀:語意上明顯是否定或退回的按鈕(顏色是危險樣式、文字寫「駁回」「退回」),事後查簽核 紀錄的動作欄位卻是 approved,不是 rejected。
原因:動作欄位不是照按鈕的顏色或文字語意決定,決定權在送出簽核時的一條獨立規則:只有當這個 按鈕「沒有配對任何出線」而且「按鈕風格是危險樣式」兩個條件同時成立,才會記成 rejected; 只要按鈕接了任何出線,不論按鈕語意上是核准、退回補件還是別的什麼,一律記成 approved。 SOC 團隊版的「封鎖攻擊來源」與「誤判結案」兩個危險樣式按鈕都配了出線,兩者都會被記成 approved,就是同一個規則。
正確做法:要知道簽核者實際選了哪個按鈕,一律去看傳出變數(output_variable 寫入 的流程變數)或簽核意見,不要只看動作欄位;真正需要記成 rejected 的按鈕,設計時就要 刻意不配對任何出線。
逾時去向沒接在目前的出線/決策清單裡,逾時功能整個悄悄不啟用
症狀:畫面上「啟用逾時自動處理」是勾選的,但案件放著不簽,過了設定的時間也完全沒有自動 改道,執行紀錄裡只留一行「逾時去向不在可選路徑內,本關卡不啟用逾時」的錯誤,不會顯示在畫面上。
原因:逾時去向記的是一個具體的出線或決策 id;改了節點的出線、或切換過自訂決策的開關、或 重新配過決策選項之後,原本記住的那個 id 可能已經不在目前算出來的可選清單裡。系統採取的是 「寧可不啟用逾時,也不要啟動一個到期後走不出去的倒數」,所以會整批放棄這次的逾時設定,但簽核本身 完全正常,不會有任何錯誤訊息浮上畫面。
正確做法:改了出線或決策選項之後,一定要重新打開簽核設定,確認「逾時去向」下拉裡目前選的 項目還在、還對;這個下拉每次開啟面板才會依當下的自訂決策或出線重新算一次清單。
WORKING 逾時模式在簽核者沒有班表時會悄悄退回 ABSOLUTE
症狀:設定成「工作時間」倒數,以為下班與假日不會計時,實際卻是連續 24 小時不間斷倒數, 跟「絕對時間」沒有兩樣。
原因:工作時間模式需要一個班表可以參照;系統會從目前的簽核者清單裡找第一個有設定班表的人 當參照對象,找不到任何人有班表時,就直接改用絕對時間倒數,不會報錯也不會有提示。
正確做法:需要「只在上班時間倒數」的效果時,先確認至少有一位簽核者已經設定了班表;企業或 帳號完全沒建過班表時,工作時間模式形同虛設。
node展覽館裡的簽核示範分兩批,都在系統預設企業(平台建置時內建、唯一看得到 node展覽館 分類的企業) 底下,每個示範都是一份完整可以送單的表單+流程:
| 批次 | 流程名稱 | 示範重點 |
|---|---|---|
| 第一批(簽核者怎麼解析) | NT-19 FormAdapter 示範(發起人自簽) | 簽核者類型 INITIATOR:誰送單,誰簽核。 |
| NT-19 FormAdapter 示範(指定人員) | 簽核者類型 USER:不論誰送單,簽核者永遠是設定裡寫死的那個人。 | |
| NT-19 FormAdapter 示範(角色@單位) | 同一個角色接兩個節點,對照 unit_scope=APPLICANT_UNIT(只認申請人所屬單位的主管)與 GLOBAL(全企業任一持有者皆可)。 | |
| NT-19 FormAdapter 示範(找不到簽核人時) | 用「分支」依表單欄位分流,對照 no_assignee_action 的 return(退回、REJECTED 終態)與 fallback_role(改派、正常等待)兩種行為。 | |
| 第二批(決策後怎麼走、沒人簽怎麼辦) | NT-19 FormAdapter 示範(自訂決策配對出線) | 三個按鈕(核准/退回補件/駁回)分別示範單一出線、迴圈出線、空出線三種設計,以及「駁回按鈕接了出線就不記成駁回」這個反直覺結果。 |
| NT-19 FormAdapter 示範(決策結果驅動後續分支) | 兩個決策刻意接到同一條出線,圖形本身分不出差異,靠傳出變數交給下游「分支」二次判斷。 | |
| NT-19 FormAdapter 示範(簽核逾時自動改道) | 送單後刻意不簽核,等它自己在 1 分鐘後逾時,自動走指定路徑並留下 action=timeout 的簽核紀錄。 |
在平台安裝目錄下(載入 .env 後)可以先列出安裝計畫,再實際佈建:
venv/bin/python scripts/seed_node_showcase.py --list
venv/bin/python scripts/seed_node_showcase.py --apply --only B5a
venv/bin/python scripts/seed_node_showcase.py --apply --only B5b
佈建完成後到表單中心的「填寫表單」分類「node展覽館」下即可送單。怎麼看結果:每個示範送單後,用對應 的示範帳號完成或刻意不完成簽核,接著查流程實例的最終狀態、簽核紀錄的動作與簽核者顯示文字、以及各示範 自己的傳出變數是否等於預期值(例如角色@單位示範的兩個傳出變數應各自反映哪一關被誰簽過)。找不到簽核人 與逾時兩個示範特別要對照「案件是直接以 REJECTED 結束」還是「留在等待中」,這正是本篇第 4、6 節說明的 行為差異。