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