 30】雙方確認后才能結案:如何聯(lián)動 Claim 與兩條 Report 狀態(tài))
【尋跡校園 HarmonyOS NEXT 實戰(zhàn) 30】雙方確認后才能結案如何聯(lián)動 Claim 與兩條 Report 狀態(tài)這是“尋跡校園 HarmonyOS NEXT 實戰(zhàn)”系列第 30 篇。本文結合HandoffService.confirmCompletion()、ClaimService.complete()、HandoffParty與本地回歸測試說明為什么一方確認只能記錄進度第二方確認后才能完成 Handoff、Claim并聯(lián)動拾得與來源丟失兩條 Report。上圖為原創(chuàng)生成的雙確認結案插畫不是應用截圖。CLAIMANT與KEEPER兩個完成信號匯合后業(yè)務才進入COMPLETED并繼續(xù)更新 Claim 和關聯(lián) Report。一、為什么一方點擊“完成”不能直接結案線下交接存在兩個不同事實拾得者確認已經(jīng)交出物品申請者確認已經(jīng)收到物品。如果任意一方單擊后就把記錄永久關閉可能出現(xiàn)“拾得者到了但沒有見到對方”“申請者拿到的不是目標物品”“一方誤點完成”等爭議。雙方確認不是形式上的兩個按鈕而是結案條件的兩個獨立證據(jù)。二、先區(qū)分“安排確認”和“完成確認”交接流程有兩層確認claimantConfirmed / keeperConfirmed雙方同意地點和時間claimantCompleted / keeperCompleted雙方確認實際交接已經(jīng)發(fā)生。安排確認只讓 Handoff 進入CONFIRMED。只有完成確認同時為真才進入COMPLETED。把這兩層混在一個布爾值里會讓“同意去圖書館見面”被誤解為“已經(jīng)收到物品”。三、HandoffParty 讓調用意圖顯式化項目用枚舉表達確認方exportenumHandoffParty{CLAIMANTCLAIMANT,KEEPERKEEPER}confirmCompletion(claimId, party)根據(jù)角色只更新一方標記。相比傳入兩個任意布爾值枚舉更容易審查也能避免調用方一次篡改雙方結果。四、只有 CONFIRMED 才允許確認完成Service 首先讀取 Handoff 并檢查if(!record||record.status!HandoffStatus.CONFIRMED){returnnewOperationResultHandoffRecord(false,雙方確認安排后才能確認已交接);}PROPOSED、RESCHEDULED、CANCELLED、EXPIRED和COMPLETED都不能進入這條寫入路徑。這防止用戶繞過地點確認也避免已結束流程被舊頁面重新修改。五、第一次完成確認為什么仍保持 CONFIRMED如果只有claimantCompleted或keeperCompleted為真Service 保存記錄但不改變 Handoff 狀態(tài)。返回文案是已記錄一方確認等待另一方確認。頁面繼續(xù)展示兩行獨立進度已確認一方按鈕禁用另一方仍可操作。用戶能看到流程在前進但不會誤以為已經(jīng)結案。六、第二次確認如何觸發(fā) COMPLETEDService 每次更新角色標記后檢查if(record.claimantCompletedrecord.keeperCompleted){record.statusHandoffStatus.COMPLETED;}只有兩個條件同時成立保存后的 Handoff 才是COMPLETED。隨后 Service 調用claimService.complete(claimId)把結果擴散到認領和報告聚合。上圖展示第二方確認后的級聯(lián)路徑Handoff 完成只是第一步Claim 和兩條關聯(lián) Report 全部更新后用戶才應看到完整結案結果。七、Claim 完成為什么要求原狀態(tài)為 ACCEPTEDClaimService.complete()只接受ACCEPTEDClaim。若申請已取消、拒絕、過期或完成調用會失敗。這條前置條件保證 Handoff 不能把一個已經(jīng)失效的認領重新結案。Handoff 和 Claim 的狀態(tài)必須相互兼容而不是誰最后寫入誰覆蓋。八、為什么要更新兩條 Report認領目標是FOUND拾得記錄可選的sourceReportId指向申請者自己的LOST丟失記錄。交接完成后拾得報告已經(jīng)找到失主應為RESOLVED來源丟失報告已經(jīng)找回物品也應為RESOLVEDClaim 為COMPLETEDHandoff 為COMPLETED。如果只關閉拾得記錄失主自己的丟失記錄仍會出現(xiàn)在候選列表繼續(xù)制造無效匹配。九、沒有 sourceReportId 時怎樣處理用戶也可能從拾得詳情直接發(fā)起認領沒有關聯(lián)自己的丟失記錄。此時sourceReportId為空。Service 始終結案目標拾得報告只在來源 ID 非空時更新第二條報告awaitreportService.markResolved(current.reportId);if(current.sourceReportId.length0){awaitreportService.markResolved(current.sourceReportId);}可選關聯(lián)不能阻止主流程完成也不能用空字符串查詢 Repository。十、結案后為什么禁止取消HandoffService.cancel()明確拒絕COMPLETED、CANCELLED和EXPIRED狀態(tài)。完成代表雙方已經(jīng)確認實際交接并且關聯(lián)記錄可能已經(jīng)從候選列表移除。普通取消按鈕不應反向打開這些實體。如果正式產(chǎn)品需要爭議申訴應新增獨立申訴流程和審計記錄而不是復用“取消安排”把歷史狀態(tài)倒退。十一、ArkUI 頁面如何表達單機角色模擬HandoffPage提供兩個按鈕“模擬拾得者確認已交出”“模擬失主確認已收到”。頁面頂部明確說明這是單機比賽演示正式版本需要兩個已驗證身份分別完成。這段文案非常重要。兩個按鈕出現(xiàn)在同一臺設備上只能證明狀態(tài)機和 UI 鏈路不能證明真實雙賬號簽名、遠程通知或防抵賴能力。十二、本地測試驗證了完整級聯(lián)回歸測試按真實順序執(zhí)行創(chuàng)建并接受 Claim使用固定地點發(fā)起 Handoff確認交接安排CLAIMANT首次確認完成斷言 Handoff 仍為CONFIRMED斷言 Claim 仍為ACCEPTEDKEEPER第二次確認完成斷言 Handoff 與 Claim 均為COMPLETED斷言目標和來源 Report 均為RESOLVED斷言完成后取消失敗。powershell-ExecutionPolicy Bypass-File.\scripts\test-local-state-machines.ps1這組斷言把“按鈕點擊成功”升級為跨實體結果驗證。十三、當前寫入順序存在重要的部分失敗窗口現(xiàn)有實現(xiàn)先把 Handoff 保存為COMPLETED再調用ClaimService.complete()。如果后續(xù) Claim 或 Report 更新失敗方法會返回失敗但 Handoff 可能已經(jīng)是COMPLETED。用戶再次調用confirmCompletion()時又會因為狀態(tài)不再是CONFIRMED而被拒絕。這是一個真實的一致性風險錯誤提示存在不代表自動補償已經(jīng)完成。十四、為什么不能把 try/catch 寫成“事務”try/catch能捕獲異常并映射用戶文案卻不會自動回滾已經(jīng)成功的 Repository 寫入。當前跨實體順序大致為順序寫入1Handoff →COMPLETED2Claim →COMPLETED3FOUND Report →RESOLVED4可選 LOST Report →RESOLVED任何后一步失敗都可能留下前面已提交的數(shù)據(jù)。準確表述應是“順序協(xié)調并返回部分失敗”而不是“事務性結案”。十五、正式版怎樣實現(xiàn)原子或可補償結案服務端可以選擇在同一事務中更新 Handoff、Claim 和兩條 Report為每條記錄增加版本號阻止并發(fā)舊寫使用結案命令 ID 保證重復請求冪等寫入 outbox 事件再由可靠消費者補齊派生狀態(tài)對部分失敗記錄建立補償任務管理端顯示不一致告警保留雙方確認時間和身份審計申訴流程不直接回滾歷史完成狀態(tài)。客戶端只應展示服務端確認后的權威結果。十六、結案后的頁面刷新應來自權威數(shù)據(jù)完成后onDataChanged()增加共享dataRevision首頁、消息和“我的發(fā)布”重新讀取 Service 數(shù)據(jù)。頁面不應該手工把多個卡片改成“已完成”。從 Repository 重新聚合能避免某一頁面漏改來源 Report也便于進程重啟后恢復一致視圖。十七、消息文案要區(qū)分三個階段用戶至少會看到三種不同結果一方已確認等待另一方雙方已確認所有實體結案成功Handoff 已完成但后續(xù)聯(lián)動失敗需要重新進入檢查。把它們全部寫成“操作成功”會掩蓋最關鍵的一致性問題。十八、真機與多用戶驗收仍缺什么當前本地測試和單機頁面可以證明主要業(yè)務規(guī)則但正式驗收還需要兩個真實賬號分別確認服務端拒絕同一賬號代替雙方并發(fā)雙擊與重試保持冪等一方離線后恢復推送和消息狀態(tài)一致進程重啟后確認標記不丟失部分失敗可以自動補償審計日志不泄露私密核驗答案申訴與爭議不會靜默篡改歷史記錄。這些均不能由當前同設備角色模擬外推。工程復盤多實體結案先列出最小一致性清單一次完整結案至少要回答五個問題Handoff 是否已經(jīng)由雙方確認完成Claim 是否從允許的狀態(tài)進入COMPLETED目標拾得 Report 是否進入RESOLVED存在來源丟失 Report 時它是否同步結束重復調用是否仍返回同一個業(yè)務結果。把這五項寫成清單比在頁面成功回調里零散修改對象更容易審查。順序寫入實現(xiàn)還要為每一步指定失敗后的動作。第一方確認只改變 Handoff 進度不觸發(fā)其余實體第二方確認觸發(fā)級聯(lián)時任何部分失敗都應保留操作 ID 和已完成步驟下一次重試從權威狀態(tài)繼續(xù)而不是從頭把終態(tài)記錄倒退。當前單機 Repository 沒有跨表事務所以文章只報告本地順序寫入和測試覆蓋并把原子性明確列為未實現(xiàn)邊界。讀取側也需要一致性保護。列表、詳情和消息頁應在結案后統(tǒng)一刷新 Service 快照如果發(fā)現(xiàn) Handoff 已完成但 Report 仍可認領應顯示可恢復錯誤并觸發(fā)受控補償不能讓兩個頁面長期展示相反結論。日志只記錄實體 ID、狀態(tài)遷移和補償結果私密核驗答案不進入結案審計。最終驗收應覆蓋順序和重復拾得者先確認、失主后確認反向順序兩方重復點擊第一方確認后重啟應用第二方確認時其中一條關聯(lián)報告缺失。每個案例都要同時斷言四類實體的權威狀態(tài)和用戶可見文案才能證明“雙方確認”不是一個局部按鈕效果。十九、本文小結雙方確認結案的核心是把“安排已同意”“拾得者已交出”“失主已收到”拆成獨立事實。第一方完成確認只記錄進度第二方確認后才觸發(fā) Handoff、Claim 和關聯(lián) Report 的聯(lián)動結案?!皩ほE校園”當前已經(jīng)用生產(chǎn) Service 和本地回退測試證明主要級聯(lián)與取消限制但跨 Repository 原子事務、真實雙賬號身份、服務端審計和部分失敗補償仍是正式版本必須解決的工程問題。系列導航第 30 篇 / 共 50 篇。上一篇《一次改期與 24 小時過期》下一篇《舉報去重與治理狀態(tài)機》。