)
目錄一、今日概覽二、快速查詢前端接入一個配置該不該復用的判斷配置獨立的決策副線菜單導入生產的層級丟失三、數據看板從整頁空白到局部降級全局兜底 vs 局部處理四、PDF 導出排障一次方案的三段反復第一段要不要裝瀏覽器第二段能不能干脆不裝瀏覽器純前端第三段回到后端渲染但修了 Host 坑五、導出報告前端化原生 HTML拒絕截圖六、發版與收尾七、復盤一條暗線脫敏說明本文內部項目以化名出現——lab-web前端、lab-aidoc/lab-biz后端、lab-agentAgent 服務、agent-web另一個前端項目。業務模塊泛化為某識別模塊/某核驗模塊等具體角色、測試文件已化名。chromedp、pandoc、k3s、Chromium、UmiJS 等開源/通用技術名詞保留原稱。今天的工作密度不小21 個 codex 會話里真正落地的開發有五攤一攤前端接入、一攤容錯改造、兩攤都圍繞導出打轉外加發版。有意思的是看似散活的幾件事背后有同一條暗線——“渲染質量取決于數據是原生還是截圖而架構位置決定了運維成本”。這個到復盤再串先按時間順序展開。一、今日概覽模塊事項類型lab-web快速查詢quick-query前端接入從 agent-web 遷移頁面功能lab-aidoc快速查詢硬編碼超時改為配置可調且配置獨立不復用 OCR 配置重構lab-web數據看板局部降級單個服務失敗不再導致整頁空白修復lab-biz/aidocPDF 導出生產排障google-chrome not found→ k3s 獨立 chromium 服務 Host 頭修復排障lab-web三個模塊導出報告從后端渲染改為前端原生 HTML 導出重構后臺菜單導入生產層級丟失修復、菜單全量移除 icon修復全棧lab-agent、lab-web 發版發版二、快速查詢前端接入一個配置該不該復用的判斷快速查詢的后端模塊早就實現了但前端一直沒接。這攤活本以為是搬頁面實際牽出一個值得記的配置取舍。頁面本身從agent-web遷過來問題不大用一份 PDF 樣本跑通流程后重點轉到后端快速查詢的 OCR走不走版面感知layout_aware流程、超時怎么管。配置獨立的決策超時原本是硬編碼的要改成配置可調。第一版順手把它掛到了現成的 OCR LLM 配置ocrllm下面——反正都是 LLM 調用復用一套配置省事。但這個省事很快被否掉了理由很直接快速查詢應該是它自己本身而不是 OCR 服務的附庸。第一版復用最終獨立被否快速查詢≠OCR快速查詢超時配置放哪?ocrllm 配置省事但耦合quick_query 自己的配置段獨立可演化這是個挺典型的判斷復用不是看現在像不像而是看以后會不會各自演化。快速查詢和 OCR 固然都要調 LLM但它們的模型選擇、超時容忍度、并發模式遲早會分叉。一旦塞進同一個配置段未來任何一方調整都得顧忌另一方。趁現在還沒有歷史依賴把它獨立出來成本最低。副線菜單導入生產的層級丟失接入過程中還插了一個后臺問題把菜單導出再導入生產環境后只有數據中心保留了原來的層級結構其余模塊全攤平成了一級菜單。根因不在導入邏輯本身而在只導了菜單表、漏了角色綁定生產的唯一角色化名某角色丟失了對父級菜單的層級綁定。修復是重建core_role_menu_ref——把那 30 條菜單按最終結構重新綁回角色。順帶把所有菜單的icon字段全量清空前端icon為空就不渲染純文本菜單更干凈。一個小教訓導數據只導主表是常見坑。菜單的層級關系除了菜單表自身的parent_code還依賴角色-菜單綁定表漏了關聯表結構就會在導入端塌掉。三、數據看板從整頁空白到局部降級數據看板頁面有個惱人的現象后端任意一個服務接口報錯整個頁面就空白其它正常的服務數據也一起看不到了。需求很明確一個服務出錯只把那一塊顯示為錯誤別拖垮整頁。全局兜底 vs 局部處理一開始想的是一勞永逸的路子——在請求層的全局回調里統一兜底或者加個統一封裝。但這條路的代價是侵入公共代碼要動utils/request.ts這種被全局引用的基礎設施影響面太大而且局部降級的策略每個頁面其實不一樣看板是分塊容錯別的頁面可能是整頁重試全局兜底很難精確表達。全局兜底局部 catch數據看板: 多個服務分塊某服務失敗整頁空白原行為僅該區塊顯示錯誤其它正常展示權衡之后走了指定頁面局部處理在每個分塊請求處單獨 catch失敗的那塊降級成錯誤態其余照常渲染。代價是每個用了多服務的頁面都得自己寫一遍 catch但它零侵入公共代碼且容錯策略完全由各頁面自己說了算。這個取舍背后有個原則容錯策略是頁面級語義不是請求級通用。一個 HTTP 500 在不同頁面的含義不同——在看板里是這一格暫時沒數據在表單提交里可能是必須重試。把它強行收進全局回調等于讓基礎設施去猜業務語義猜不準就會在某個頁面出錯。所以寧可每個頁面多寫幾行 catch也不讓公共代碼背上它不該懂的語義。順帶澄清了一個小疑惑登錄后落地頁其實是數據看板history.replace(/data-board)那個帶3 條熱點新聞/國產化率目標的歡迎頁是純靜態硬編碼、不調任何接口的備用入口——所以它永遠不會空白。四、PDF 導出排障一次方案的三段反復這攤最有故事性。生產環境arm下載報告 PDF 直接報錯chromedp PDF 生成失敗: exec: google-chrome: executable file not found in $PATH后端用 chromedp 驅動 Chrome 把頁面渲染成 PDF但生產鏡像里壓根沒裝 Chrome。圍繞怎么讓它能用方案來回擺了三下。鏡像爆炸大別的服務也需要不想裝瀏覽器截圖實現→模糊分頁生硬報錯: google-chrome not found方案1: 給業務鏡像裝 Chrome方案2: k3s 內獨立 chromium 服務方案3: 純前端導出截圖質量不達標Host 頭校驗坑修: 服務名解析成 ClusterIP用 IP 請求? 后端渲染方案打通第一段要不要裝瀏覽器給業務鏡像塞 Chrome 是最直覺的但立刻被否——鏡像會膨脹得很難看而且不止這一個服務需要瀏覽器。于是傾向k3s 里跑一個獨立的 chromium 服務大家共用。第二段能不能干脆不裝瀏覽器純前端期間認真評估了純前端導出想借此甩掉瀏覽器依賴。但實測下來踩了兩個坑截圖方式導出畫面發虛柵格化的天然短板而且分頁很生硬把一整頁 DOM 截成圖片再切表格/文字會被攔腰截斷。對于內容是長文本情報速遞一期幾十條新聞全文的報告截圖方案的質量過不了關。這一段的價值不在結論而在把純前端的邊界摸清了截圖導出只適合所見即所得的單屏內容不適合長內容、要分頁、要清晰文字的報告。第三段回到后端渲染但修了 Host 坑最終情報速遞還是走后端 chromedp k3s 獨立 chromium 服務。但獨立服務又撞出一個隱蔽的坑Chrome 的遠程調試端口會校驗 Host 頭只接受localhost或 IP。用 k8s 服務名比如某chromium服務去請求DNS 解析沒問題、路由也通請求確實到了瀏覽器 Pod卻被 Chrome 自己的 Host 校驗擋了回來。修復不在 k8s 配置層而在代碼里后端把服務名解析成 ClusterIP再用http://ClusterIP:9222發請求——Host 頭變成 IPChrome 就放行了。Service → Pod 的轉發 k8s 本來就處理好了所以 yaml 一行不用改。http://某chromium服務:9222Host服務名Host 校驗拒絕只認 localhost/IP先解析服務名→ClusterIPhttp://IP:9222HostIPHostIP 放行后端Chrome 遠程調試端口? 被擋ClusterIPChrome? 渲染成功這是個非常容易誤判的坑——報錯像網絡問題其實是瀏覽器自己的安全校驗。如果一味去查 k8s 網絡/DNS/Service會繞很大彎子。最后還差一塊節點上得放中文字體思源黑體否則渲染出來的 PDF 中文全是方塊。這是 arm 生產環境常見配置缺失和代碼無關但少了它整套方案就白搭。五、導出報告前端化原生 HTML拒絕截圖排障期間順帶推動了另一個方向的重構把三個模塊情報速遞、某識別模塊、某核驗模塊的導出報告從后端渲染改成前端導出。這里有個明確的硬約束必須用原生導出不能用截圖等捷徑——這正是上一節截圖模糊/分頁生硬教訓的直接延伸。也評估過 pandocHTML → PDF但最終選定原生 HTML 渲染 瀏覽器打印/下載這條路建一個共享導出工具渲染一份 HTML 文檔走瀏覽器原生的打印/下載保留原報告模板的樣式不是另起爐灶而是把后端模板移植到前端某核驗模塊的字段原本是后端預渲染好的改造成后端把原始字段放開給前端前端用原模板渲染——這樣前端拿的是原生數據而非截圖這條路和第四節的 chromedp 方案看似矛盾其實是按場景分工情報速遞內容長、要分頁、且已有成熟后端渲染保留 chromedp而這三個模塊的報告結構更適合前端原生渲染、且能省掉對瀏覽器服務的依賴。沒有銀彈按每個導出的內容形態選方案。六、發版與收尾lab-agent前后端發版lab-web提交推送數據看板降級、快速查詢接入等PDF Host 修復提交發版構建 #139新鏡像含修復七、復盤一條暗線把今天幾攤活串起來看有一條暗線渲染質量取決于數據是原生還是截圖而在哪里渲染決定了運維成本。截圖永遠是下策。數據看板的降級、PDF 導出的反復、導出前端化的硬約束三次都指向同一個結論截圖/柵格化會丟掉原生 DOM 的清晰度和分頁能力。需要可讀、可分頁的內容必須用原生數據 原生渲染。在哪里渲染是架構選擇題不是技術細節。后端渲染chromedp質量好但要養一個瀏覽器服務、還附帶 Host 校驗/字體/鏡像體積等運維成本前端渲染省依賴但要自己處理分頁和樣式。今天的每個導出模塊都按自己的內容形態在這個光譜上選了位置沒有一刀切。復用看未來不看現在。快速查詢配置要不要掛到 OCR 配置下看的不是現在都調 LLM而是以后會不會各自演化。耦合一旦形成拆的成本永遠比現在獨立高。容錯是頁面語義別塞進基礎設施。全局請求回調懂不了這一格失敗該不該拖垮整頁所以局部降級留給頁面自己寫。公共代碼保持不懂業務的克制。報錯像網絡問題未必是網絡問題。chromedp 的 Host 頭校驗坑偽裝成了 k8s 連通性問題。遇到路由通了但被拒先想想是不是目標服務自己的安全校驗。