據(jù)字典離線網(wǎng)頁版制作詳解:從數(shù)據(jù)庫到零依賴靜態(tài)頁面)
簡介面向用友NC Cloud 2105用戶的離線數(shù)據(jù)字典以網(wǎng)頁形式收錄了系統(tǒng)核心數(shù)據(jù)表、字段、索引、視圖及業(yè)務(wù)對象關(guān)聯(lián)信息適合實(shí)施顧問、開發(fā)人員、數(shù)據(jù)庫管理員和業(yè)務(wù)分析師查閱也可作為企業(yè)數(shù)字化轉(zhuǎn)型中理解數(shù)據(jù)模型的基礎(chǔ)資料。這一版本經(jīng)過細(xì)致校對修正消除了原始文檔中的常見不一致問題內(nèi)容準(zhǔn)確性有保障同時無需聯(lián)網(wǎng)即可在瀏覽器中快速檢索十分適合無網(wǎng)絡(luò)或弱網(wǎng)環(huán)境。資源共11203個文件其中11191個html頁面承載數(shù)據(jù)字典正文另配少量js、css、gif用于頁面交互與樣式呈現(xiàn)壓縮包整體僅2.98MB輕量易部署。目前已有706人學(xué)習(xí)瀏覽。借助這份資料讀者可以按模塊梳理客戶、供應(yīng)商、庫存、訂單等業(yè)務(wù)實(shí)體及數(shù)據(jù)表結(jié)構(gòu)理解權(quán)限與角色劃分、接口集成規(guī)范并參考其中關(guān)于查詢報(bào)表與數(shù)據(jù)庫調(diào)優(yōu)的說明更高效地支撐NCC2105的實(shí)施和日常運(yùn)維。1. 為什么要把NCC2105數(shù)據(jù)字典做成離線網(wǎng)頁版1.1 原始需求從哪來做過NCC2105二次開發(fā)的朋友應(yīng)該都有過這種經(jīng)歷剛接手一個項(xiàng)目還沒開始寫代碼先被一摞表結(jié)構(gòu)文檔勸退了。NCC2105作為成熟的ERP產(chǎn)品后臺表數(shù)量輕輕松松上千張字段更是上萬起步業(yè)務(wù)表、中間表、配置表、日志表混在一起如果不依賴數(shù)據(jù)字典連“這個字段到底存的是什么”都搞不清楚。最原始的做法是直接連數(shù)據(jù)庫查。開發(fā)環(huán)境有權(quán)限還好說生產(chǎn)環(huán)境給你只讀賬號都算客氣很多時候只能找DBA要一份導(dǎo)出。就算拿到了視圖翻起來也極不順手字段注釋、枚舉值、主外鍵關(guān)系全擠在一起。更麻煩的是項(xiàng)目組里不同角色的人都在頻繁翻閱同一份字典前端要看狀態(tài)位含義后端要核對字段類型測試要確認(rèn)邊界值一份好用的字典幾乎是全組剛需。1.2 三個核心痛點(diǎn)缺一不可做這個離線網(wǎng)頁版之前我先后試過幾種形態(tài)最終確定了三個必須滿足的條件。第一必須離線可用。項(xiàng)目現(xiàn)場經(jīng)常是內(nèi)網(wǎng)環(huán)境甚至客戶機(jī)房都不讓帶外部設(shè)備進(jìn)去線上文檔、云端筆記全部失效。把字典做成一個本地網(wǎng)頁文件雙擊就能打開不依賴任何服務(wù)器和網(wǎng)絡(luò)環(huán)境這才叫真正的隨時可查。第二必須帶全局搜索。NCC2105的表名是NX開頭加數(shù)字不熟悉的人根本記不住靠肉眼在一千多張表里找目標(biāo)那不是在查字典是在練眼力。支持按表名、按表注釋、按字段名、按字段注釋模糊搜索這才算達(dá)到“字典”的及格線。第三必須有層級導(dǎo)航。NCC2105的表有清晰的模塊歸屬比如基礎(chǔ)檔案、供應(yīng)鏈、財(cái)務(wù)、人力資源等這些信息藏在表名前綴或元數(shù)據(jù)分類里。一個好的字典頁面應(yīng)該能先按模塊縮小范圍再精確定位到具體表最后查看字段明細(xì)。層級導(dǎo)航加搜索兩條路徑互補(bǔ)才是完整的檢索體驗(yàn)。2. 方案選型我為什么放棄PDF最終選了純靜態(tài)網(wǎng)頁2.1 PDF方案的致命缺陷很多人第一反應(yīng)是導(dǎo)成PDF我最早也這么干過。工具也好找數(shù)據(jù)庫客戶端基本都自帶導(dǎo)出功能選好表就能生成一份幾十頁甚至上百頁的PDF。真正用起來才發(fā)現(xiàn)問題一堆。PDF是靜態(tài)排版內(nèi)容不會變但NCC2105的表結(jié)構(gòu)是動態(tài)的二次開發(fā)過程中經(jīng)常會加字段、改注釋、調(diào)整長度。PDF只要導(dǎo)出一版這張表就“過期”了想更新必須重新導(dǎo)出整份文檔然后重復(fù)發(fā)給所有人。字典本該是隨時查閱的參考工具而不是一份需要反復(fù)替換的存檔文件。還有個很實(shí)際的問題PDF的搜索體驗(yàn)非常差。Adobe Reader的CtrlF只能逐頁跳轉(zhuǎn)對上千張表來說基本形同虛設(shè)。手機(jī)上打開更是災(zāi)難頁面縮放、排版錯亂字小到要拿放大鏡看。字段描述和枚舉值在PDF里往往擠在一個大單元格里閱讀體驗(yàn)遠(yuǎn)談不上友好。2.2 離線網(wǎng)頁版的兩個路線對比確定要做網(wǎng)頁版之后我評估了兩條實(shí)現(xiàn)路線。第一條是搭建Web服務(wù)方案典型做法是用Python的Flask或Django寫一個后臺數(shù)據(jù)放SQLite通過瀏覽器訪問。好處是查詢能力強(qiáng)支持復(fù)雜篩選缺點(diǎn)是必須啟動服務(wù)現(xiàn)場機(jī)器可能沒裝Python環(huán)境即便裝好了進(jìn)程掛了又得有人去重啟。第二條就是最終采用的純靜態(tài)方案把所有表結(jié)構(gòu)數(shù)據(jù)預(yù)生成成一個JSON文件配合一個HTML頁面用瀏覽器直接打開file://協(xié)議訪問。沒有任何服務(wù)端進(jìn)程沒有依賴安裝一個文件夾拷到哪都能用。搜索、導(dǎo)航、字段明細(xì)全部在前端完成。兩條路線的取舍本質(zhì)是你更在乎查詢能力的上限還是部署的零門檻。對于NCC2105數(shù)據(jù)字典這種“低頻高可靠性”工具零門檻部署的優(yōu)先級遠(yuǎn)高于復(fù)雜查詢能力。JSON文件雖然需要全量加載但幾千張表、幾萬個字段的結(jié)構(gòu)化數(shù)據(jù)壓縮后通常只有幾MB現(xiàn)代瀏覽器解析起來完全沒有壓力。2.3 “完美修正版本”到底修正了什么標(biāo)題里提到“完美修正版本”是因?yàn)樵缦任易鲞^一個初版用起來有幾個明顯缺陷這次一并處理掉了。第一個缺陷是搜索邏輯太“笨”。初版用簡單的includes匹配搜“供應(yīng)商”會把所有注釋里帶“供應(yīng)商”三個字的表全部撈出來結(jié)果幾百條等于沒搜。修正版改成了分詞匹配加權(quán)重排序完全匹配的表名排最前注釋包含關(guān)鍵詞的表名次之字段命中再次之。這樣搜索“供應(yīng)商”不再是海撈而是真正給你一條有優(yōu)先級的檢索列表。第二個缺陷是字段枚舉值缺失。NCC2105很多字段是字符型存數(shù)字編碼比如單據(jù)狀態(tài)存0、1、2如果不看枚舉文檔根本不知道0代表什么。初版漏掉了這部分修正版把字段的enum取值說明也納入生成邏輯在字段詳情中一并展示查字典的時候不用再另開一張枚舉對照表。第三個缺陷是移動端適配太差。現(xiàn)場調(diào)試、去車間看問題經(jīng)常是拿手機(jī)臨時查一下。初版沒有做響應(yīng)式布局手機(jī)上頁面縮放錯位表格擠成一團(tuán)。修正版對卡片式布局做了全面適配PC端左右分欄手機(jī)端上下堆疊滿足了現(xiàn)場隨時查的需求。這三個修正點(diǎn)看起來不大但每一項(xiàng)都直接影響日常使用體驗(yàn)也是我在實(shí)際項(xiàng)目中反復(fù)碰壁后才意識到的。3. 核心實(shí)現(xiàn)細(xì)節(jié)從NCC2105數(shù)據(jù)庫到離線頁面的全鏈路3.1 第一步從元數(shù)據(jù)抽取表結(jié)構(gòu)NCC2105的數(shù)據(jù)庫基于Oracle或PostgreSQL表結(jié)構(gòu)的元數(shù)據(jù)存儲在系統(tǒng)表中。以O(shè)racle為例核心信息從ALL_TAB_COLUMNS、ALL_COL_COMMENTS、ALL_TAB_COMMENTS這三張視圖取。用一條SQL就能獲得表名、表注釋、字段名、字段類型、字段長度、字段注釋等信息SELECT c.table_name, tc.comments AS table_comment, c.column_name, c.data_type, c.data_length, cc.comments AS column_comment FROM all_tab_columns c LEFT JOIN all_tab_comments tc ON c.table_name tc.table_name LEFT JOIN all_col_comments cc ON c.table_name cc.table_name AND c.column_name cc.column_name WHERE c.owner NCC_USER ORDER BY c.table_name, c.column_id;這里有個容易踩的坑如果owner不寫會把系統(tǒng)表、臨時表全部掃出來數(shù)據(jù)量爆炸且沒有任何參考價值。NCC2105的業(yè)務(wù)表統(tǒng)一在特定schema下寫SQL時務(wù)必帶上owner條件。提取完字段信息還需要補(bǔ)一張“表級維度”的清單每張表屬于哪個業(yè)務(wù)模塊、是主表還是子表、核心邏輯主鍵是什么。這些信息不在系統(tǒng)表里需要結(jié)合NCC2105的建模規(guī)范來判斷。我根據(jù)表名前綴和NCC的元數(shù)據(jù)分類做了映射比如以bd開頭的表屬于基礎(chǔ)數(shù)據(jù)以po開頭的是采購訂單模塊以so開頭的是銷售模塊。把模塊信息拼進(jìn)表清單導(dǎo)航才能按“模塊分組”來組織。3.2 第二步生成結(jié)構(gòu)化JSON數(shù)據(jù)原始SQL查詢結(jié)果是二維表結(jié)構(gòu)不適合前端頁面直接使用。我寫了一個Python腳本把查詢結(jié)果轉(zhuǎn)換成嵌套JSON結(jié)構(gòu)大致是{ modules: [ { name: 采購管理, tables: [ { tableName: po_order, comment: 采購訂單主表, columns: [ { name: pk_order, type: varchar2(20), comment: 訂單主鍵, enumValue: }, { name: billstatus, type: int, comment: 單據(jù)狀態(tài), enumValue: 0:自由, 1:審批中, 2:已生效, 3:關(guān)閉 } ] } ] } ] }關(guān)鍵點(diǎn)在于枚舉值的整合。NCC2105的枚舉信息通常散落在代碼里、配置表里或者干脆只有老員工口口相傳。我的做法是在生成腳本里維護(hù)一份“字段枚舉值映射表”定期從開發(fā)環(huán)境中核對補(bǔ)齊。對于沒有枚舉信息的字段enumValue字段留空字符串前端就不顯示枚舉區(qū)塊保持頁面干凈。數(shù)據(jù)量方面NCC2105完整庫大概有1500張表1.8萬個字段生成后的JSON大約4MB左右不壓縮也能接受。但如果未來要擴(kuò)展到更多項(xiàng)目建議對JSON做一次Gzip體積能壓縮到1MB以內(nèi)。3.3 第三步前端頁面實(shí)現(xiàn)與檢索邏輯前端使用純原生HTMLCSSJavaScript不引入任何框架理由很簡單框架需要構(gòu)建、需要CDN、需要npm install這些在離線環(huán)境全是障礙。原生三件套寫完之后整個字典就是一個文件夾放U盤里甚至可以直接拷給同事。頁面布局采用左右兩欄左側(cè)是模塊樹和表名列表右側(cè)展示選中表的字段明細(xì)。頂部放一個全局搜索框輸入關(guān)鍵詞后左側(cè)列表實(shí)時刷新為搜索結(jié)果。搜索邏輯是這套頁面的靈魂。我實(shí)現(xiàn)了一個簡單的加權(quán)評分函數(shù)表名完全等于關(guān)鍵詞權(quán)重100表名以關(guān)鍵詞開頭權(quán)重80表名包含關(guān)鍵詞權(quán)重60表注釋包含關(guān)鍵詞權(quán)重40字段名包含關(guān)鍵詞權(quán)重20字段注釋包含關(guān)鍵詞權(quán)重10每個結(jié)果取最高權(quán)重作為排序依據(jù)同時顯示命中的字段信息。這個設(shè)計(jì)看似簡單實(shí)際使用效果遠(yuǎn)超初版的“無腦includes”方案。搜索“客戶”時客戶主表排在前面而客戶名稱字段命中的結(jié)果排在后面用戶一眼就能找到最核心的表。3.4 性能優(yōu)化幾萬字段的搜索如何做到秒開有人說才4MB的數(shù)據(jù)不至于談性能吧。但最開始我確實(shí)踩過性能坑。初版搜索是遍歷所有表的字段做循環(huán)匹配每次輸入一個字符就全量跑一遍在低配辦公本上明顯卡頓。后來做了三處優(yōu)化整個體驗(yàn)就順了。第一處是輸入防抖。用戶停止輸入300毫秒后才觸發(fā)搜索而不是每個字符都觸發(fā)。第二處是數(shù)據(jù)預(yù)索引。頁面加載時把所有字段的“表名字段名注釋”拼接成一個長字符串?dāng)?shù)組搜索時只需遍歷這個預(yù)先打平的索引不用反復(fù)嵌套訪問對象。第三處是結(jié)果數(shù)量限制。搜索列表最多渲染前100條結(jié)果避免DOM一次性插入過多節(jié)點(diǎn)導(dǎo)致頁面無響應(yīng)。這三處優(yōu)化沒有用到任何高深技術(shù)但實(shí)實(shí)在在地把搜索響應(yīng)時間從幾百毫秒降到了幾乎無感知。性能優(yōu)化這件事很多時候不是靠框架而是靠“減少無用功”。4. 實(shí)測記錄與問題排查4.1 常見問題速查表版本做出來之后我讓項(xiàng)目組幾位同事各用了兩周收集到一批真實(shí)反饋整理成表格。問題現(xiàn)象原因分析解決方法雙擊html文件后頁面空白瀏覽器禁止本地文件讀取外部JSON將JSON文件改為內(nèi)聯(lián)到HTML中打包成一個單文件搜索中文關(guān)鍵詞無結(jié)果JSON編碼不是UTF-8中文亂碼生成腳本中強(qiáng)制指定encodingutf-8Oracle的CLOB字段顯示為[CLOB]查詢結(jié)果未做類型轉(zhuǎn)換SQL中用DBMS_LOB.SUBSTR轉(zhuǎn)換為字符串部分表注釋為空開發(fā)階段未維護(hù)注釋生成腳本跳過空注釋并在前端顯示“無注釋”表名點(diǎn)擊后字段明細(xì)加載慢每次點(diǎn)擊都重建表格DOM改為預(yù)渲染所有表詳情CSS控制顯隱4.2 幾個值得說的坑與教訓(xùn)第一個坑是瀏覽器安全策略。HTML用file://協(xié)議打開時瀏覽器出于安全考慮會攔截本地JSON文件的異步請求控制臺報(bào)CORS錯誤。這個問題我排查了大半天一度以為是代碼寫錯了。后來發(fā)現(xiàn)解決方案無非兩種要么把JSON轉(zhuǎn)成JS文件通過script標(biāo)簽引用要么啟動一個本地靜態(tài)服務(wù)器但這就違背了“零部署”的初衷。我最終選擇將JSON內(nèi)容直接內(nèi)聯(lián)進(jìn)HTML雖然文件變大了一些但徹底規(guī)避了跨域問題單文件拷貝非常方便。第二個坑是Oracle大小寫敏感。NCC2105數(shù)據(jù)庫里表名既有大寫又有小寫如果不加處理前端按字母排序時會混亂。我在生成腳本中對表名統(tǒng)一做了大寫處理同時保留原始表名用于實(shí)際SQL查詢時復(fù)制使用。這個細(xì)節(jié)看似微不足道但確實(shí)影響日常使用的觀感。第三個坑是枚舉值數(shù)據(jù)的準(zhǔn)確性。一次更新時我把某個狀態(tài)字段的枚舉值寫錯了導(dǎo)致組里同事按錯誤值去排查數(shù)據(jù)浪費(fèi)了半天時間。從那以后我養(yǎng)成了一個習(xí)慣任何枚舉值變更必須在生成腳本的映射表里同步修改并且導(dǎo)出前自動打印一份變更日志人工確認(rèn)無誤后再生成HTML。數(shù)據(jù)字典這種工具內(nèi)容出錯比沒有更可怕。5. 幾個可以繼續(xù)擴(kuò)展的方向離線網(wǎng)頁版做到這個程度核心需求已經(jīng)全部滿足了但用久了之后我自己的體會是它還有幾個值得繼續(xù)深挖的方向。一個方向是支持增量更新。現(xiàn)在的流程是數(shù)據(jù)庫結(jié)構(gòu)變化后必須重新跑一次完整腳本再打包。對于頻繁迭代的開發(fā)項(xiàng)目來說這個操作頻率其實(shí)挺高的。如果能在頁面里內(nèi)置一個“數(shù)據(jù)更新”入口允許導(dǎo)入一份增量JSON就能省去重新打包的步驟對多人協(xié)作場景會友好很多。另一個方向是加入表間關(guān)系可視化。NCC2105的主外鍵關(guān)系比較隱蔽依賴字段命名規(guī)范和ER圖才能看清。如果能從數(shù)據(jù)庫約束或數(shù)據(jù)流中解析出表間關(guān)聯(lián)在前端以簡單的父子關(guān)系列表形式展示排查問題時能省不少事。不需要畫復(fù)雜的關(guān)系圖列出來就夠了。還有一個小方向是導(dǎo)出能力收口。現(xiàn)在字典只能看如果要引文檔到項(xiàng)目周報(bào)或交付物里還得手動復(fù)制粘貼。如果給每張表加一個“導(dǎo)出Markdown”按鈕一鍵生成當(dāng)前表的字典片段對交付文檔的整理會非常方便。這些方向我目前都只是在腦子里過了一遍還沒有全部落地。但數(shù)據(jù)字典這種工具本質(zhì)上是越用越順手、越迭代越貼合團(tuán)隊(duì)習(xí)慣的東西每次小改動都能帶來實(shí)打?qū)嵉男侍嵘1疚倪€有配套的精品資源點(diǎn)擊獲取