值預(yù)填:少填一半字段的配置實(shí)戰(zhàn)與避坑指南)
1. 為什么這種小功能反而值得單獨(dú)寫一篇先說結(jié)論RAP 的 Action Popup 預(yù)填默認(rèn)值是我最近在調(diào)流程配置時(shí)覺得最“不起眼但真能省事”的功能之一。在 RAP這類流程編排平臺(tái)大家應(yīng)該不陌生里彈窗Popup是用戶和流程交互最頻繁的入口。尤其是 Action 類型的 Popup——用戶點(diǎn)一個(gè)按鈕彈出一個(gè)表單填一堆字段再點(diǎn)確認(rèn)——這套交互本身沒什么技術(shù)含量但問題恰恰出在“填一堆字段”上。很多業(yè)務(wù)彈窗里真正需要用戶手動(dòng)輸入的字段其實(shí)沒幾個(gè)大部分字段的值要么是固定的、要么是從上下文里能拿到的、要么是上一次操作時(shí)已經(jīng)選過的。如果每個(gè)彈窗都讓用戶從零開始填體驗(yàn)差不說還特別容易填錯(cuò)。而Default Values Function要解決的問題就是讓這些“其實(shí)不用用戶填”的字段自動(dòng)帶上默認(rèn)值。說直白點(diǎn)用戶打開彈窗時(shí)表單里已經(jīng)幫他填好大半了他只需要?jiǎng)幽菐讉€(gè)真正需要他決定的字段。我當(dāng)時(shí)是在調(diào)一個(gè)“工單批量指派”的 Action Popup 時(shí)開始認(rèn)真用這個(gè)功能的。彈窗里有負(fù)責(zé)人、優(yōu)先級(jí)、截止時(shí)間、備注、是否通知相關(guān)人員總共五六個(gè)字段。如果用默認(rèn)配置用戶每次都要重新選負(fù)責(zé)人、重新選優(yōu)先級(jí)、重新填備注。但實(shí)際業(yè)務(wù)里負(fù)責(zé)人大概率是當(dāng)前登錄用戶優(yōu)先級(jí)大概率繼承上級(jí)工單備注大部分時(shí)候是空著不填的。這幾個(gè)字段如果能在彈窗打開時(shí)就預(yù)填好用戶每次操作至少能少點(diǎn)四五次。這篇文章不打算講那種“照著文檔做一遍就完事”的教程。我會(huì)把我在實(shí)際配置里的思路、每一步的取舍、以及最后踩的坑都寫出來。如果你正在處理 RAP 里類似的彈窗體驗(yàn)問題這篇文章應(yīng)該能幫你省下不少試錯(cuò)的時(shí)間。2. Default Values Function 的工作原理與配置入口2.1 它到底是個(gè)什么機(jī)制要理解 Default Values Function得先知道 RAP 的 Action Popup 是怎么渲染出來的。簡(jiǎn)單說Popup 里的每個(gè)字段在打開前都會(huì)經(jīng)過一個(gè)“取值”的階段。這個(gè)階段會(huì)決定字段初始顯示什么值。取值優(yōu)先級(jí)大致是用戶之前在這個(gè)彈窗里提交過、但還沒關(guān)閉頁面時(shí)暫存的值配置里寫死的Fixed Value通過Default Values Function動(dòng)態(tài)計(jì)算出來的值字段本身的默認(rèn)值。Default Values Function 就處于第三層。它本質(zhì)上是一個(gè)可編程的取值器——你給它一段邏輯它根據(jù)當(dāng)前的上下文、關(guān)聯(lián)數(shù)據(jù)、用戶信息等輸入返回一個(gè)字段值的映射。RAP 拿到這個(gè)映射后會(huì)在彈窗打開前把它應(yīng)用到對(duì)應(yīng)字段上。聽起來很抽象我換個(gè)方式說。你可以在 Default Values Function 里寫類似這樣的邏輯偽代碼function getDefaultValues(context) { return { assignee: context.currentUser, priority: context.relatedTicket.priority, dueDate: addDays(new Date(), 3) }; }當(dāng)彈窗打開時(shí)assignee字段自動(dòng)填成當(dāng)前登錄用戶priority自動(dòng)帶出關(guān)聯(lián)工單的優(yōu)先級(jí)dueDate自動(dòng)算好三天后。整個(gè)過程對(duì)用戶來說是無感的——他只看到彈窗打開就已經(jīng)填好了完全不需要手動(dòng)改。這就是 Default Values Function 的核心價(jià)值它不是幫你把字段默認(rèn)值寫死而是讓你根據(jù)當(dāng)前場(chǎng)景實(shí)時(shí)計(jì)算出最合適的預(yù)填值。2.2 配置入口在哪里我以目前比較常見的 RAP 版本為例。配置路徑一般是流程配置 → 找到目標(biāo) Action → 編輯 Popup 配置 → 字段設(shè)置 → 默認(rèn)值來源 → 選擇“Default Values Function”不同版本可能菜單位置略有差異但基本邏輯是統(tǒng)一的先找到你要配置的 Action點(diǎn)開它的彈窗配置頁再找到字段級(jí)別的默認(rèn)值設(shè)置。需要注意的是Default Values Function 可以配置在整個(gè) Popup 級(jí)別一次返回多個(gè)字段的默認(rèn)值也可以配置在單個(gè)字段級(jí)別只對(duì)特定字段生效。我個(gè)人的習(xí)慣是優(yōu)先在 Popup 級(jí)別配置因?yàn)樽侄味嗔艘院蠹泄芾肀确稚⑴渲煤镁S護(hù)得多。配置界面一般長(zhǎng)這樣一個(gè)代碼編輯器支持 JavaScript 或類 JavaScript 語法一個(gè)“測(cè)試”按鈕可以模擬上下文并查看返回結(jié)果一個(gè)返回值說明通常是對(duì)象格式鍵是字段名值是對(duì)應(yīng)的默認(rèn)值。第一次配置的時(shí)候我建議先寫一個(gè)最簡(jiǎn)單的函數(shù)返回一個(gè)空對(duì)象{}然后點(diǎn)測(cè)試確認(rèn)鏈路通了再開始加實(shí)際邏輯。這樣能快速區(qū)分“函數(shù)本身寫錯(cuò)了”和“函數(shù)沒被調(diào)用”這兩種完全不同的情況。2.3 它的執(zhí)行時(shí)機(jī)與限制這里有個(gè)容易誤解的點(diǎn)Default Values Function 不是每次打開彈窗都會(huì)執(zhí)行。它只在彈窗首次初始化、且字段尚未有用戶輸入值的時(shí)候執(zhí)行。如果你在彈窗打開后改了某個(gè)字段的值然后關(guān)掉再打開在未提交的情況下RAP 可能保留你上次輸入的臨時(shí)值而不會(huì)重新執(zhí)行 Default Values Function 去覆蓋它。這就引出一個(gè)關(guān)鍵限制Default Values Function 不適合用來做“每次打開都強(qiáng)制刷新默認(rèn)值”的場(chǎng)景。如果你需要用戶每次打開彈窗都看到最新值比如截止時(shí)間永遠(yuǎn)是“今天3天”你需要保證彈窗被正確關(guān)閉或提交而不是使用暫存機(jī)制。另外Default Values Function 是在前端執(zhí)行的。所以它拿不到后端數(shù)據(jù)庫里那些沒有暴露到上下文的字段。如果你需要從某個(gè)業(yè)務(wù)表中取最新的一條記錄作為默認(rèn)值得先把數(shù)據(jù)準(zhǔn)備好放到上下文里或者通過關(guān)聯(lián)查詢接口來獲取。2.4 為什么說它是彈窗體驗(yàn)的“第一層減負(fù)”回到文章標(biāo)題用戶少填一半。這句話不是夸張——在大多數(shù) Action Popup 里真正需要用戶介入的字段通常不超過兩三個(gè)。剩下的字段要么可以從上下文推導(dǎo)要么可以由業(yè)務(wù)規(guī)則計(jì)算。Default Values Function 正好把后面這類字段全部自動(dòng)化了。我在實(shí)際配置后統(tǒng)計(jì)過一個(gè)彈窗的操作時(shí)長(zhǎng)。沒配默認(rèn)值之前用戶平均要花 30 秒左右填完并提交配了之后直接點(diǎn)確認(rèn)就能走完流程的大概占 60%剩下的用戶也只需要改一兩個(gè)字段。操作時(shí)長(zhǎng)降到了差不多 15 秒有些熟練用戶甚至 10 秒內(nèi)就完成了。這個(gè)提升對(duì)高頻操作來說感受是非常明顯的。3. 從零配置一個(gè)預(yù)填示例以“批量指派工單”為例3.1 業(yè)務(wù)場(chǎng)景與字段梳理我拿一個(gè)最典型的場(chǎng)景來講批量指派工單。假設(shè)你現(xiàn)在有一個(gè) Action叫“指派工單”點(diǎn)擊后彈窗讓用戶填寫負(fù)責(zé)人下拉選擇用戶優(yōu)先級(jí)下拉低/中/高/緊急截止時(shí)間日期選擇處理備注多行文本是否通知相關(guān)人員開關(guān)關(guān)聯(lián)客戶下拉選擇客戶。如果全都不預(yù)填用戶每次都要一個(gè)個(gè)手動(dòng)選。而且根據(jù)經(jīng)驗(yàn)用戶在對(duì)著一堆空白字段時(shí)往往會(huì)猶豫——比如優(yōu)先級(jí)到底選高還是緊急截止時(shí)間到底給不給緩沖期。但如果彈窗打開時(shí)這些字段已經(jīng)帶出了合理的默認(rèn)值用戶就會(huì)傾向于“默認(rèn)值合理我就不改不合適我再調(diào)”決策成本一下子低了很多。那這些字段到底怎么填默認(rèn)值我按字段逐一分析負(fù)責(zé)人大部分場(chǎng)景下操作人就是負(fù)責(zé)人。所以默認(rèn)值就是context.currentUser。優(yōu)先級(jí)當(dāng)前登錄用戶在配置里可能有默認(rèn)偏好或者可以繼承被指派工單本身的優(yōu)先級(jí)。這里設(shè)計(jì)為“繼承工單優(yōu)先級(jí)”。截止時(shí)間可以取當(dāng)前時(shí)間2個(gè)工作日或者基于工單的緊急程度動(dòng)態(tài)計(jì)算。處理備注大部分時(shí)候是空著但如果你有固定的處理套路可以預(yù)填一句常用模板用戶不滿意再改。是否通知相關(guān)人員默認(rèn)打開符合“指派后通知”的業(yè)務(wù)習(xí)慣。關(guān)聯(lián)客戶從工單上下文里自動(dòng)帶出用戶基本不用動(dòng)。梳理完字段后你會(huì)發(fā)現(xiàn)大部分字段的默認(rèn)值都能從上下文或業(yè)務(wù)規(guī)則里推導(dǎo)出來。這就是 Default Values Function 能發(fā)揮最大價(jià)值的地方。3.2 編寫 Default Values Function 的完整步驟下面我給出一個(gè)可以直接套用的函數(shù)寫法以 JavaScript 語法為例function getDefaultValues(context) { const defaults {}; // 1. 負(fù)責(zé)人默認(rèn)是當(dāng)前登錄用戶 defaults.assignee context.currentUser; // 2. 優(yōu)先級(jí)繼承關(guān)聯(lián)工單的優(yōu)先級(jí)取不到就默認(rèn)“中” defaults.priority context.relatedTicket ? context.relatedTicket.priority : medium; // 3. 截止時(shí)間根據(jù)優(yōu)先級(jí)動(dòng)態(tài)計(jì)算 const now new Date(); if (context.relatedTicket context.relatedTicket.priority urgent) { // 緊急工單當(dāng)天 defaults.dueDate now; } else if (context.relatedTicket context.relatedTicket.priority high) { // 高優(yōu)先級(jí)1天 defaults.dueDate new Date(now.getTime() 24 * 60 * 60 * 1000); } else { // 默認(rèn)3天 defaults.dueDate new Date(now.getTime() 3 * 24 * 60 * 60 * 1000); } // 4. 通知相關(guān)人員默認(rèn)開啟 defaults.notifyParties true; // 5. 關(guān)聯(lián)客戶從上下文中帶出 if (context.relatedTicket context.relatedTicket.customer) { defaults.customer context.relatedTicket.customer; } return defaults; }寫完之后在配置界面的測(cè)試區(qū)里模擬一下上下文比如傳入一個(gè)帶有currentUser和relatedTicket的對(duì)象確認(rèn)函數(shù)返回值符合預(yù)期。這一步非常重要因?yàn)?Default Values Function 的一個(gè)常見坑就是上下文字段名對(duì)不上——你以為是context.currentUser實(shí)際配置里可能叫context.user或context.operator。測(cè)試能幫你立刻暴露這個(gè)問題。3.3 關(guān)鍵字段的默認(rèn)值設(shè)計(jì)邏輯上面這個(gè)函數(shù)里有幾個(gè)設(shè)計(jì)點(diǎn)值得多說幾句負(fù)責(zé)人的默認(rèn)值為什么是當(dāng)前用戶而不是上一個(gè)操作人因?yàn)橹概晒芜@個(gè)動(dòng)作天然是“當(dāng)前用戶把活派給別人”但很多時(shí)候操作人就是最終處理人。設(shè)置成當(dāng)前用戶后絕大多數(shù)情況下直接確認(rèn)就行如果真的是指派給別人用戶再下拉改一下就好。這個(gè)默認(rèn)值設(shè)計(jì)的原則是“讓最可能的值出現(xiàn)在第一位”。優(yōu)先級(jí)的繼承邏輯如果關(guān)聯(lián)工單本身已經(jīng)是“緊急”了那默認(rèn)值再填“中”顯然不合理。繼承規(guī)則能最大限度減少用戶調(diào)整。同時(shí)也給了高級(jí)優(yōu)先級(jí)更短的截止時(shí)間這是一組聯(lián)動(dòng)設(shè)計(jì)——優(yōu)先級(jí)變了截止時(shí)間也跟著變。這樣用戶在改優(yōu)先級(jí)時(shí)截止時(shí)間的默認(rèn)值也會(huì)自動(dòng)調(diào)整而不是一成不變。通知開關(guān)默認(rèn)開啟從業(yè)務(wù)角度來說指派后通知相關(guān)人員是標(biāo)準(zhǔn)動(dòng)作所以默認(rèn)開啟比默認(rèn)關(guān)閉更能減少漏通知的情況。這種開關(guān)類字段默認(rèn)值應(yīng)該往“安全”方向靠而不是往“省事”方向靠。3.4 配置完成后如何自測(cè)配置完一定要自測(cè)別直接上線。我的自測(cè)步驟一般是這樣用測(cè)試工具模擬上下文檢查函數(shù)返回值。重點(diǎn)看字段名是否匹配、默認(rèn)值是否符合預(yù)期、異常情況下比如relatedTicket為空是否能兜底。實(shí)際打開彈窗看渲染效果。這一步最容易發(fā)現(xiàn)“函數(shù)返回了但字段沒生效”的問題比如字段類型不匹配日期傳成了字符串、或者字段在 Popup 配置里沒用對(duì)編輯器類型。測(cè)試用戶修改后重開彈窗。確認(rèn)臨時(shí)值不會(huì)覆蓋默認(rèn)值或者確認(rèn)這是你想要的交互。提交一條真實(shí)數(shù)據(jù)。確保預(yù)填的值能正常提交并保存不會(huì)因?yàn)槟J(rèn)值格式問題導(dǎo)致后端校驗(yàn)失敗。我見過不少配置了 Default Values Function 但沒自測(cè)的人上線后用戶反饋“彈窗打開是空的”或者“日期顯示成 Invalid Date”。這些問題基本都是自測(cè)不足導(dǎo)致的。4. 默認(rèn)值函數(shù)里的常見翻車現(xiàn)場(chǎng)與排查鏈路4.1 上下文結(jié)構(gòu)對(duì)不上最常見的靜默失敗前面提到過上下文結(jié)構(gòu)不熟悉是新手第一大坑。這個(gè)問題最惡心的地方在于——函數(shù)不報(bào)錯(cuò)但返回的字段就是沒生效。舉例你在函數(shù)里寫context.currentUser.id但平臺(tái)傳進(jìn)來的上下文里用戶對(duì)象叫context.user而且id字段叫user_id。函數(shù)執(zhí)行時(shí)context.currentUser是 undefined于是context.currentUser.id直接拋異常。如果平臺(tái)的異常處理是靜默的只記錄日志不彈錯(cuò)誤你看到的現(xiàn)象就是彈窗正常打開但字段全部是空的。排查鏈路我建議這樣走先在測(cè)試工具里打印完整上下文console.log(JSON.stringify(context))看看實(shí)際的數(shù)據(jù)結(jié)構(gòu)對(duì)照字段名逐一修正不要靠猜直接把測(cè)試工具里拿到的字段名復(fù)制到函數(shù)里測(cè)試環(huán)境驗(yàn)證一次確認(rèn)返回的鍵名和 Popup 字段編碼完全一致再打開真實(shí)彈窗驗(yàn)證。這個(gè)排查鏈路看似簡(jiǎn)單但很多人會(huì)跳過第一步直接改函數(shù)反復(fù)試錯(cuò)浪費(fèi)大量時(shí)間。先打印上下文永遠(yuǎn)是最高效的做法。4.2 字段類型不匹配日期和數(shù)字的隱形坑RAP 的 Popup 字段是有類型的比如日期字段、數(shù)字字段、下拉字段。Default Values Function 返回的值如果類型不對(duì)渲染時(shí)就會(huì)出問題。我踩過的具體坑是日期字段。我在函數(shù)里返回了一個(gè) JavaScript 的Date對(duì)象測(cè)試時(shí)返回值看著沒問題但真實(shí)彈窗里字段顯示成了Invalid Date。后來查了下發(fā)現(xiàn)平臺(tái)內(nèi)部對(duì)日期字段的期望格式是字符串比如2025-01-15而我在函數(shù)里返回的是Date對(duì)象內(nèi)部序列化時(shí)轉(zhuǎn)換失敗最終渲染異常。解決方案很簡(jiǎn)單返回之前把值格式化成平臺(tái)期望的類型。function formatDate(date) { const y date.getFullYear(); const m String(date.getMonth() 1).padStart(2, 0); const d String(date.getDate()).padStart(2, 0); return ${y}-${m}-$gv5xshg9wyt; }同理數(shù)字字段返回字符串也可能導(dǎo)致下拉選項(xiàng)匹配不上。建議統(tǒng)一以平臺(tái)定義的字段類型為準(zhǔn)而不是以 JavaScript 默認(rèn)類型為準(zhǔn)。遇到字段類型相關(guān)的疑問時(shí)直接在自測(cè)時(shí)用真實(shí)彈窗驗(yàn)證一下比看文檔快得多。4.3 函數(shù)被重復(fù)執(zhí)行副作用問題Default Values Function 從設(shè)計(jì)上說應(yīng)該是純函數(shù)——相同輸入得到相同輸出且不改變外部狀態(tài)。但實(shí)際配置場(chǎng)景里總有人忍不住在里面寫一些“額外操作”比如更新某個(gè)變量、往 localStorage 里存數(shù)據(jù)、甚至調(diào)用接口。這在單次執(zhí)行時(shí)沒問題但如果平臺(tái)在彈窗打開前多次調(diào)用函數(shù)比如每個(gè)字段單獨(dú)調(diào)一次、或者渲染時(shí)重復(fù)取默認(rèn)值你的副作用操作就會(huì)被執(zhí)行多次。輕則沒有明顯影響重則導(dǎo)致數(shù)據(jù)混亂。我自己就遇到過有人沒錯(cuò)就是我自己早期干過在 Default Values Function 里試圖更新一個(gè)用于計(jì)數(shù)的全局變量。每次打開彈窗這個(gè)計(jì)數(shù)都會(huì)增加好幾次因?yàn)楹瘮?shù)被調(diào)用了不止一次。后來查平臺(tái)日志才發(fā)現(xiàn)彈窗初始化階段函數(shù)被調(diào)了三四次。所以不要在 Default Values Function 里做任何有副作用的操作。如果你確實(shí)需要根據(jù)額外數(shù)據(jù)計(jì)算默認(rèn)值應(yīng)該確保數(shù)據(jù)已經(jīng)準(zhǔn)備好并放到上下文里或者在函數(shù)里只做純計(jì)算。4.4 邏輯兜底不足空值導(dǎo)致彈窗直接白屏另一個(gè)常見問題是——你以為某個(gè)上下文值一定存在但某些場(chǎng)景下它就是沒傳。舉個(gè)例子context.relatedTicket在從工單詳情打開彈窗時(shí)是存在的但如果你是跨模塊直接調(diào)用這個(gè) ActionrelatedTicket可能就沒了。如果函數(shù)里不加判空就直接取context.relatedTicket.priority就會(huì)拋異常異常如果沒被平臺(tái)捕獲結(jié)果可能就是彈窗打不開或者打開后白屏。所以無論你多確定某個(gè)值一定存在都要加一層默認(rèn)值兜底const priority context.relatedTicket ? context.relatedTicket.priority : medium;對(duì)于這種問題我的自測(cè)清單里永遠(yuǎn)有一條模擬“缺少 part of context”的情況確保函數(shù)能優(yōu)雅降級(jí)。測(cè)的時(shí)候可以把上下文換成空的看看函數(shù)返回什么然后根據(jù)結(jié)果補(bǔ)兜底。5. 進(jìn)階玩法讓默認(rèn)值隨用戶行為“越用越聰明”5.1 根據(jù)用戶歷史偏好動(dòng)態(tài)調(diào)整Default Values Function 不僅能做靜態(tài)推導(dǎo)還可以做得更聰明——根據(jù)當(dāng)前用戶的近期操作記錄推斷出他偏好怎么填。例如“優(yōu)先級(jí)”這個(gè)字段不同用戶的口味不同。有的用戶傾向于把所有工單都標(biāo)成“高”有的用戶習(xí)慣標(biāo)“中”。如果你的系統(tǒng)能拿到當(dāng)前用戶最近幾次操作里的優(yōu)先級(jí)選擇記錄可以在函數(shù)里做加權(quán)統(tǒng)計(jì)取出現(xiàn)頻率最高的值作為默認(rèn)值。偽代碼思路function getDefaultValues(context) { const history context.userActionHistory || []; if (history.length 0) { return { priority: medium }; } const count {}; history.forEach(item { const p item.priority; count[p] (count[p] || 0) 1; }); // 選擇出現(xiàn)次數(shù)最多的優(yōu)先級(jí) let bestPriority medium; let maxCount 0; Object.keys(count).forEach(p { if (count[p] maxCount) { maxCount count[p]; bestPriority p; } }); return { priority: bestPriority }; }這就是所謂的“越用越聰明”——默認(rèn)值不再是拍腦袋寫死的而是隨著用戶行為動(dòng)態(tài)調(diào)整。不過要注意這個(gè)功能依賴上下文里能傳入用戶歷史操作數(shù)據(jù)。如果拿不到歷史數(shù)據(jù)這個(gè)玩法就玩不了。我建議你在配置之前先確認(rèn)一下平臺(tái)的上下文里有沒有類似字段。5.2 聯(lián)動(dòng)多字段的條件默認(rèn)值默認(rèn)值之間可以互相聯(lián)動(dòng)。比如你根據(jù)優(yōu)先級(jí)計(jì)算截止時(shí)間這已經(jīng)是一種聯(lián)動(dòng)更復(fù)雜的可以做到選完客戶后自動(dòng)帶出客戶的默認(rèn)負(fù)責(zé)人選完工單類型后自動(dòng)帶出該類型對(duì)應(yīng)的處理模板。這種聯(lián)動(dòng)的實(shí)現(xiàn)方式通常不是在 Default Values Function 里做——因?yàn)楹瘮?shù)只在彈窗初始化時(shí)執(zhí)行它沒法響應(yīng)用戶后續(xù)的字段變化。更合理的做法是給某些字段配置“值改變時(shí)重新計(jì)算相關(guān)字段”的聯(lián)動(dòng)邏輯或者在前端事件里調(diào)用一個(gè)類似的計(jì)算函數(shù)。但 Default Values Function 本身可以返回多組聯(lián)動(dòng)默認(rèn)值比如function getDefaultValues(context) { if (context.ticketType bug) { return { priority: urgent, dueDate: formatDate(new Date()), template: Bugs are prioritized and expected to be resolved within 24 hours. }; } if (context.ticketType feature) { return { priority: high, dueDate: formatDate(addDays(new Date(), 5)), template: Feature request, please evaluate and provide implementation plan. }; } return { priority: medium, dueDate: formatDate(addDays(new Date(), 3)), template: }; }這種寫法特別適合工單類型、服務(wù)類型這類“決定彈窗整體填法”的前置字段。一旦類型確定其他字段的默認(rèn)值幾乎就能一起確定。5.3 多級(jí)彈窗中的默認(rèn)值傳遞如果你的 Action Popup 是多級(jí)的比如第一步選類型第二步填詳情默認(rèn)值的傳遞就變得很重要。RAP 里多級(jí) Popup 通常會(huì)把第一級(jí)選中的值作為上下文的一部分傳給第二級(jí)。所以 Default Values Function 可以直接基于上一級(jí)的值來預(yù)填后續(xù)字段。這里有一個(gè)常見問題兩級(jí)彈窗之間共享的上下文字段名很容易記錯(cuò)。我在一次配置里把第一級(jí)的字段編碼寫成了type但第二級(jí)的上下文里傳過來的字段名是selectedType導(dǎo)致第二級(jí)函數(shù)死活取不到值。最后還是靠打印上下文才發(fā)現(xiàn)的。所以多級(jí)彈窗的配置建議是每一級(jí)的 Default Values Function 都先打印一下上下文確認(rèn)字段名后再開始寫實(shí)際邏輯。6. 把默認(rèn)值做成一種配置規(guī)范實(shí)戰(zhàn)后的經(jīng)驗(yàn)沉淀6.1 為每個(gè) Popup 字段明確默認(rèn)值策略多次配置之后我養(yǎng)成了一個(gè)習(xí)慣不是上來就寫函數(shù)而是先做一個(gè)字段級(jí)別的默認(rèn)值策略表。這個(gè)表長(zhǎng)這樣字段默認(rèn)值來源動(dòng)態(tài)性兜底值負(fù)責(zé)人當(dāng)前用戶動(dòng)態(tài)無優(yōu)先級(jí)繼承關(guān)聯(lián)工單動(dòng)態(tài)中截止時(shí)間優(yōu)先級(jí)聯(lián)動(dòng)動(dòng)態(tài)當(dāng)前時(shí)間3天處理備注固定模板固定空是否通知固定開啟固定true關(guān)聯(lián)客戶關(guān)聯(lián)工單客戶動(dòng)態(tài)無有了這個(gè)表寫 Default Values Function 就變成了一件機(jī)械活照著表里的策略一行行實(shí)現(xiàn)就行。而且后續(xù)維護(hù)也方便——業(yè)務(wù)策略變了改表格再改函數(shù)不會(huì)漏字段。我覺得這是配置類項(xiàng)目里最值得養(yǎng)成的習(xí)慣。因?yàn)閺棿白侄我欢嗄愫苋菀讓懼鴮懼屯四硞€(gè)字段有沒有設(shè)默認(rèn)值。策略表能讓你一眼看清整體情況。6.2 維護(hù)一份函數(shù)代碼的“分層寫法”代碼寫多了以后我推薦按照下面的層次來組織 Default Values Function入口層定義getDefaultValues(context)負(fù)責(zé)調(diào)度字段計(jì)算層每個(gè)字段一個(gè)獨(dú)立的小函數(shù)比如calcAssignee(context)、calcPriority(context)、calcDueDate(context)工具層通用函數(shù)比如日期格式化、加減工作日。這樣做的好處是單個(gè)字段的默認(rèn)值邏輯發(fā)生變更時(shí)你只需要改那一個(gè)小函數(shù)不影響其他字段而且測(cè)試時(shí)可以單獨(dú)驗(yàn)證每個(gè)小函數(shù)。一個(gè)簡(jiǎn)化示例function getDefaultValues(context) { return { assignee: calcAssignee(context), priority: calcPriority(context), dueDate: calcDueDate(context), notifyParties: true }; } function calcAssignee(context) { return context.currentUser || ; } function calcPriority(context) { return context.relatedTicket ? context.relatedTicket.priority : medium; } function calcDueDate(context) { return formatDate(addBusinessDays(new Date(), calcPriority(context) urgent ? 0 : 3)); }這種寫法一開始會(huì)多花一點(diǎn)時(shí)間但等到你要維護(hù)五六個(gè)彈窗、每個(gè)彈窗七八個(gè)字段的時(shí)候你就會(huì)感激當(dāng)初這個(gè)決定。6.3 測(cè)試用例也要沉淀最后講一下測(cè)試。Default Values Function 看似簡(jiǎn)單但一旦規(guī)則復(fù)雜測(cè)試就必不可少。我習(xí)慣在每個(gè)函數(shù)的注釋里寫清楚測(cè)試場(chǎng)景比如// 測(cè)試用例 // 1. context.currentUser 存在 - assignee 當(dāng)前用戶 // 2. context.currentUser 不存在 - assignee // 3. relatedTicket.priority urgent - priority urgent, dueDate 今天 // 4. relatedTicket 不存在 - priority medium, dueDate 今天3天平臺(tái)如果自帶測(cè)試工具就直接用如果沒有也可以寫一段模擬上下文的小腳本把函數(shù)跑一遍。關(guān)鍵是別偷懶跳過測(cè)試——尤其是涉及日期計(jì)算和聯(lián)動(dòng)邏輯的時(shí)候一個(gè)小小的邊界條件錯(cuò)誤可能到用戶手上才會(huì)被發(fā)現(xiàn)。7. 最后我實(shí)際用得最順手的一個(gè)小技巧從第一次配置 Default Values Function 到現(xiàn)在它在我的 RAP 系列配置里已經(jīng)成了一個(gè)標(biāo)準(zhǔn)步驟。幾乎每個(gè) Action Popup 上線前我都會(huì)問自己一個(gè)問題“如果用戶打開彈窗后完全不改任何字段直接點(diǎn)確認(rèn)結(jié)果是不是合理的”如果答案是“合理”那默認(rèn)值策略就做對(duì)了如果答案是“會(huì)出問題”那就說明默認(rèn)值設(shè)計(jì)還不合格。以及一個(gè)小經(jīng)驗(yàn)?zāi)J(rèn)值是給絕大多數(shù)用戶省事的不是給所有用戶定死的。所以不要把默認(rèn)值設(shè)計(jì)成“強(qiáng)制正確”的方案而要設(shè)計(jì)成“大概率正確”的方案。留出修改空間甚至允許用戶清空字段都比讓用戶每次從頭填要好得多。如果你正準(zhǔn)備優(yōu)化自己的 RAP 流程彈窗建議先從一兩個(gè)高頻 Action 開始把默認(rèn)值函數(shù)配好、測(cè)好、上線看效果。真的跑一遍之后你會(huì)發(fā)現(xiàn)“用戶少填一半”一點(diǎn)都不夸張。