限控制:超越DAX的3種動態(tài)導(dǎo)航與視圖切換方案)
1. 項目概述當(dāng)DAX不是唯一解在Power BI的日常開發(fā)中權(quán)限控制是個繞不開的話題。一提到它很多人的第一反應(yīng)就是DAX——用USERPRINCIPALNAME()函數(shù)結(jié)合一堆IF和SWITCH判斷在數(shù)據(jù)模型里構(gòu)建復(fù)雜的行級安全性RLS規(guī)則。這確實是官方主推、文檔最全的方案。但最近在幾個項目里我被客戶問住了“我們有些報表頁面只想給經(jīng)理看有些頁面是給專員用的而且頁面之間導(dǎo)航邏輯還挺復(fù)雜能用DAX實現(xiàn)嗎” 仔細(xì)一想還真有點棘手。DAX RLS的核心是數(shù)據(jù)行級別的過濾它作用于整個數(shù)據(jù)模型。這意味著一旦你為某個角色設(shè)置了RLS規(guī)則這個規(guī)則會影響所有用到該數(shù)據(jù)表的可視化對象你很難精細(xì)地控制到“某個特定的頁面”對某個用戶不可見。頁面權(quán)限的本質(zhì)是UI/視圖層的控制這和DAX擅長的數(shù)據(jù)層控制在邏輯上屬于兩個層面。于是“非DAX方式實現(xiàn)按頁面權(quán)限控制”這個需求就浮出水面了。這不僅僅是技術(shù)上的替代方案更是對Power BI作為一款企業(yè)級報表工具在應(yīng)對復(fù)雜組織架構(gòu)和審批流程時靈活性的考驗。它適用于那些權(quán)限劃分不依賴于具體數(shù)據(jù)行而依賴于報表功能模塊的場景。比如銷售總監(jiān)看全局儀表盤和利潤分析頁區(qū)域經(jīng)理只能看自己區(qū)域的業(yè)績明細(xì)頁又或者應(yīng)收賬款數(shù)據(jù)預(yù)警頁面只對財務(wù)風(fēng)控團隊開放其他業(yè)務(wù)人員只能查看常規(guī)流水頁面。接下來我就結(jié)合實戰(zhàn)拆解幾種經(jīng)過驗證的、不寫一行DAX就能實現(xiàn)頁面級權(quán)限控制的思路。2. 核心思路拆解從數(shù)據(jù)層到展示層的權(quán)限遷移要實現(xiàn)非DAX的頁面權(quán)限控制我們必須把思維從“用數(shù)據(jù)過濾決定誰能看什么”轉(zhuǎn)變?yōu)椤坝脤?dǎo)航邏輯決定誰能看到什么頁面”。核心思路可以歸結(jié)為一點將權(quán)限判斷的時機前置并利用Power BI的頁面導(dǎo)航、書簽、可視化對象可見性等交互功能動態(tài)地構(gòu)建出針對不同用戶的專屬報表視圖。2.1 為什么DAX RLS難以實現(xiàn)精細(xì)頁面控制首先我們需要徹底理解DAX RLS的局限性這樣才能明白為何要尋找其他路徑。作用域是整個模型RLS規(guī)則定義在表上。例如你為Sales表創(chuàng)建規(guī)則[Region] LOOKUPVALUE(User[Region], User[Email], USERPRINCIPALNAME())。那么任何使用Sales表的圖表無論是在“總覽”頁還是“明細(xì)”頁都會受到同樣的區(qū)域過濾。你無法讓這個規(guī)則只在“頁面A”生效而在“頁面B”失效。無法直接隱藏頁面Power BI沒有提供基于DAX表達(dá)式來顯示或隱藏整個報表頁面的原生功能。頁面是報表的容器其可見性不由數(shù)據(jù)模型直接驅(qū)動。權(quán)限邏輯與業(yè)務(wù)邏輯耦合復(fù)雜的頁面權(quán)限常常涉及用戶角色、部門、模塊等多維屬性。將這些邏輯全部用DAX編寫會使得度量值和模型變得異常復(fù)雜且難以維護尤其是當(dāng)權(quán)限需要頻繁調(diào)整時。因此我們的新思路是在報表加載時或用戶交互時就根據(jù)其身份決定向他展示哪些頁面入口以及何種頁面布局。2.2 權(quán)限控制的三種非DAX實現(xiàn)路徑基于上述思路我總結(jié)出三種主流且實用的實現(xiàn)路徑它們可以單獨使用也可以組合起來應(yīng)對更復(fù)雜的場景。路徑一利用“按鈕導(dǎo)航”與“頁面書簽”構(gòu)建動態(tài)菜單這是最直觀、用戶體驗也相對較好的一種方式。核心思想是創(chuàng)建一個“主頁”或“導(dǎo)航頁”這個頁面上沒有任何敏感數(shù)據(jù)只有一系列導(dǎo)航按鈕。每個按鈕代表一個功能頁面如“利潤分析”、“應(yīng)收賬款預(yù)警”。系統(tǒng)根據(jù)當(dāng)前登錄用戶的身份動態(tài)顯示或隱藏對應(yīng)的導(dǎo)航按鈕。用戶只能點擊他可見的按鈕跳轉(zhuǎn)到被授權(quán)的頁面。路徑二使用“字段參數(shù)”與“條件格式”模擬頁面切換這種方法更巧妙它實際上并不進行頁面跳轉(zhuǎn)而是在同一個報表頁面上通過用戶的選擇來切換完全不同的可視化內(nèi)容集。你可以創(chuàng)建一個“字段參數(shù)”Field Parameter讓用戶選擇要查看的“模塊”如“模塊A銷售總覽”、“模塊B預(yù)警詳情”。然后通過度量值和條件格式控制當(dāng)選擇不同模塊時顯示哪一組視覺對象隱藏另一組。對于用戶而言感覺就像切換了頁面但實際上他們從未離開過一個物理頁面。路徑三基于Power BI服務(wù)“應(yīng)用”的發(fā)布隔離這是一種管理層面的解決方案嚴(yán)格來說不屬于報表開發(fā)技巧但在企業(yè)部署中非常有效。即為不同的用戶群體創(chuàng)建不同的Power BI報表文件每個文件只包含該群體有權(quán)訪問的頁面。然后通過Power BI服務(wù)上的“應(yīng)用”Apps功能將不同的報表發(fā)布給不同的用戶組。用戶通過訪問不同的應(yīng)用鏈接進入不同的報表環(huán)境。這種方式權(quán)限邊界最清晰但報表的維護成本會成倍增加。接下來的部分我將重點深入講解路徑一動態(tài)導(dǎo)航菜單和路徑二單頁多視圖的完整實現(xiàn)方案因為這兩者最具技術(shù)普適性和靈活性。3. 方案一動態(tài)導(dǎo)航菜單的實現(xiàn)詳解這個方案的目標(biāo)是打造一個智能的報表門戶。用戶登錄后首先看到一個干凈的導(dǎo)航頁頁面上只羅列著他有權(quán)限訪問的報表頁面入口。3.1 準(zhǔn)備工作構(gòu)建權(quán)限映射表一切始于數(shù)據(jù)。我們需要在Power Query中構(gòu)建一個本地權(quán)限表或者連接到一個已有的權(quán)限系統(tǒng)如數(shù)據(jù)庫中的用戶-頁面映射表。這里以本地表為例。進入Power Query編輯器在Power BI Desktop中點擊“轉(zhuǎn)換數(shù)據(jù)”。新建空白查詢選擇“新建源” - “空查詢”。輸入M語言代碼構(gòu)建表將查詢名稱改為PagePermission在高級編輯器中輸入以下M代碼。這個表結(jié)構(gòu)定義了哪個用戶或用戶組可以訪問哪個報表頁面。let Source Table.FromRows({ {zhangsancompany.com, Sales_Overview, 銷售總覽}, {zhangsancompany.com, Profit_Analysis, 利潤分析}, {lisicompany.com, Sales_Overview, 銷售總覽}, {lisicompany.com, Receivable_Alert, 應(yīng)收賬款預(yù)警}, {wangwucompany.com, Profit_Analysis, 利潤分析} }, type table [ UserEmail Text.Type, PageName Text.Type, // 對應(yīng)報表頁面的名稱英文用于邏輯判斷 PageDisplayName Text.Type // 頁面顯示名稱中文用于按鈕顯示 ]) in Source注意UserEmail字段應(yīng)與Power BI服務(wù)中用戶的登錄郵箱一致。PageName必須與報表中實際頁面的名稱在“頁面”面板中看到的名稱嚴(yán)格匹配區(qū)分大小寫。這是實現(xiàn)準(zhǔn)確導(dǎo)航的關(guān)鍵。3.2 創(chuàng)建導(dǎo)航主頁與判斷邏輯設(shè)計導(dǎo)航主頁新建一個報表頁面命名為Home。將其設(shè)置為“報表頁”的默認(rèn)視圖在頁面格式設(shè)置中。創(chuàng)建用戶身份度量值雖然我們不用DAX做權(quán)限過濾但需要一個DAX度量值來獲取當(dāng)前用戶身份用于后續(xù)查詢。在數(shù)據(jù)視圖中新建度量值CurrentUser USERPRINCIPALNAME()創(chuàng)建“可用頁面”表我們需要一個只包含當(dāng)前用戶有權(quán)訪問頁面的表。新建一個計算表建模視圖 - 新建表MyAllowedPages FILTER( PagePermission, PagePermission[UserEmail] [CurrentUser] )這個MyAllowedPages表是一個動態(tài)篩選的表只包含當(dāng)前登錄用戶的權(quán)限記錄。3.3 使用“按鈕”和“書簽”實現(xiàn)導(dǎo)航這是實現(xiàn)動態(tài)顯示的核心交互環(huán)節(jié)。在主頁插入按鈕在Home頁從“插入”選項卡添加多個“按鈕”。為每個你擁有的報表頁面都創(chuàng)建一個按鈕例如“銷售總覽按鈕”、“利潤分析按鈕”、“預(yù)警詳情按鈕”。為按鈕設(shè)置書簽首先導(dǎo)航到目標(biāo)頁面如Sales_Overview頁。在“視圖”選項卡中打開“書簽”窗格。點擊“添加”創(chuàng)建一個新書簽命名為GoTo_SalesOverview。務(wù)必在書簽窗格中選中該書簽點擊右側(cè)“...”取消勾選“數(shù)據(jù)”選項。這非常重要它確保書簽只記錄頁面和視覺對象狀態(tài)而不記錄切片器等數(shù)據(jù)過濾狀態(tài)避免導(dǎo)航時帶來意外的數(shù)據(jù)過濾。重復(fù)此過程為每個需要導(dǎo)航的頁面創(chuàng)建書簽。動態(tài)控制按鈕可見性回到Home頁選中“銷售總覽按鈕”。在“可視化”窗格的“格式”選項卡下找到“常規(guī)” - “可見性”旁邊的“fx”按鈕按規(guī)則設(shè)置格式。將“基于字段設(shè)置格式”選擇為MyAllowedPages[PageName]。設(shè)置規(guī)則如果字段值 值 輸入“Sales_Overview”與你權(quán)限表中的PageName和報表頁面名一致。然后設(shè)置滿足條件時的樣式為“開”不滿足為“關(guān)”。原理MyAllowedPages表里只存在當(dāng)前用戶有權(quán)限的頁面記錄。我們檢查Sales_Overview這條記錄是否存在。如果存在按鈕顯示如果MyAllowedPages表中根本沒有Sales_Overview這條記錄說明用戶無權(quán)限則按鈕自動隱藏。為按鈕綁定書簽動作保持按鈕選中狀態(tài)在“格式”窗格切換到“操作”選項卡。將“類型”設(shè)置為“書簽”。在“書簽”下拉列表中選擇剛才創(chuàng)建的GoTo_SalesOverview。重復(fù)步驟3和4為“利潤分析按鈕”、“預(yù)警詳情按鈕”等所有按鈕分別設(shè)置其可見性規(guī)則指向?qū)?yīng)的PageName和書簽動作。至此一個基礎(chǔ)的動態(tài)導(dǎo)航菜單就完成了。發(fā)布到Power BI服務(wù)后用戶zhangsan登錄他只會看到“銷售總覽”和“利潤分析”按鈕點擊即可跳轉(zhuǎn)。而lisi登錄則能看到“銷售總覽”和“應(yīng)收賬款預(yù)警”按鈕。3.4 方案一的注意事項與進階技巧權(quán)限表維護權(quán)限映射表最好來自數(shù)據(jù)庫或SharePoint列表便于IT部門集中管理。使用本地表僅適用于小型、靜態(tài)團隊。頁面名稱一致性權(quán)限表中的PageName、報表頁面名稱、按鈕可見性規(guī)則中判斷的字符串三者必須完全一致建議使用英文標(biāo)識符以減少編碼問題。處理無權(quán)限用戶如果用戶沒有任何頁面權(quán)限MyAllowedPages表為空所有按鈕都會隱藏導(dǎo)致主頁空白??梢钥紤]設(shè)置一個默認(rèn)的“無權(quán)限提示”視覺對象其可見性規(guī)則與MyAllowedPages表是否為空可用COUNTROWS(MyAllowedPages)0作為度量值判斷相關(guān)聯(lián)。組合權(quán)限與角色上述例子是基于用戶個體的。如果想基于角色如“經(jīng)理”、“專員”只需在權(quán)限表中將UserEmail字段替換為Role字段并創(chuàng)建一個新的“用戶-角色”映射表。判斷邏輯改為當(dāng)前用戶屬于某個角色即可看到該角色對應(yīng)的頁面按鈕。4. 方案二單頁多視圖字段參數(shù)法實現(xiàn)詳解對于頁面內(nèi)容結(jié)構(gòu)相似、但數(shù)據(jù)維度或詳細(xì)程度不同的權(quán)限場景動態(tài)導(dǎo)航可能顯得繁瑣。這時在單頁面內(nèi)通過用戶選擇來切換“視圖模塊”是更優(yōu)雅的解決方案。Power BI的“字段參數(shù)”功能是實現(xiàn)此方案的利器。假設(shè)我們有一個“財務(wù)分析”頁面高級經(jīng)理可以看到包含“毛利率”、“凈利率”、“現(xiàn)金流預(yù)測”的完整視圖而普通專員只能看到“收入”和“成本”的基礎(chǔ)視圖。4.1 創(chuàng)建“視圖模塊”字段參數(shù)新建字段參數(shù)在“建?!边x項卡下點擊“字段參數(shù)” - “新建”。配置參數(shù)名稱View Module在“字段”列表中我們不是添加數(shù)據(jù)字段而是通過添加“度量值”來定義不同的視圖。首先你需要為每個視圖模塊創(chuàng)建專用的“容器度量值”。創(chuàng)建視圖容器度量值這些度量值本身不執(zhí)行計算只作為開關(guān)標(biāo)識。View_Basic 0 // 基礎(chǔ)視圖標(biāo)識 View_Advanced 0 // 高級視圖標(biāo)識 View_FinanceOnly 0 // 財務(wù)專用視圖標(biāo)識完成字段參數(shù)創(chuàng)建在字段參數(shù)設(shè)置界面點擊“添加字段”從度量值列表中選擇View_Basic和View_Advanced。系統(tǒng)會自動生成一個View Module參數(shù)表包含View Module顯示名稱和View Module Field對應(yīng)的度量值兩列。4.2 設(shè)計頁面與條件格式控制現(xiàn)在我們在同一個報表頁面上布置兩套不同的視覺對象集一套給基礎(chǔ)視圖一套給高級視圖。布置視覺對象在頁面上創(chuàng)建兩組圖表。例如組A基礎(chǔ)視圖一個收入折線圖一個成本柱狀圖。組B高級視圖在組A的基礎(chǔ)上增加一個毛利率瀑布圖和一個現(xiàn)金流卡片圖。使用字段參數(shù)控制顯示我們的目標(biāo)是當(dāng)用戶在切片器中選擇“基礎(chǔ)視圖”時只顯示組A的圖表選擇“高級視圖”時顯示組B的圖表。這無法通過字段參數(shù)直接實現(xiàn)。我們需要一個中間判斷度量值。創(chuàng)建一個決定視覺對象是否可見的度量值ShowVisual_Basic SELECTEDVALUE(View Module[View Module Field]) [View_Basic]這個度量值返回TRUE或FALSE。當(dāng)用戶在參數(shù)切片器中選擇“基礎(chǔ)視圖”時SELECTEDVALUE(View Module[View Module Field])的值就是[View_Basic]度量值即0等式成立返回TRUE。為視覺對象設(shè)置條件格式可見性選中“收入折線圖”屬于基礎(chǔ)視圖組在格式窗格的“常規(guī)”-“可見性”處點擊“fx”。基于字段設(shè)置格式選擇度量值ShowVisual_Basic。設(shè)置規(guī)則如果值 值輸入1因為TRUE在比較中被視為1。滿足條件時“開”不滿足時“關(guān)”。為“成本柱狀圖”重復(fù)此步驟。為高級視圖創(chuàng)建控制度量值同理創(chuàng)建另一個度量值ShowVisual_Advanced SELECTEDVALUE(View Module[View Module Field]) [View_Advanced]并為毛利率瀑布圖和現(xiàn)金流卡片圖設(shè)置可見性規(guī)則綁定到此度量值。4.3 將視圖模塊與用戶權(quán)限掛鉤現(xiàn)在我們有了可以切換的視圖但還需要自動根據(jù)用戶身份來決定默認(rèn)顯示哪個視圖甚至隱藏他無權(quán)選擇的選項。創(chuàng)建用戶-視圖映射表在Power Query中創(chuàng)建或連接一個表例如UserViewMapping包含UserEmail和AllowedView字段AllowedView的值對應(yīng)View_Basic,View_Advanced等度量值名稱。動態(tài)篩選字段參數(shù)這是關(guān)鍵一步。我們需要修改View Module參數(shù)表使其僅包含當(dāng)前用戶有權(quán)訪問的視圖選項。創(chuàng)建一個新的計算表作為過濾后的參數(shù)源FilteredViewParameter VAR CurrentUser USERPRINCIPALNAME() VAR AllowedViewForUser CALCULATETABLE( VALUES(UserViewMapping[AllowedView]), UserViewMapping[UserEmail] CurrentUser ) RETURN FILTER( View Module, View Module[View Module Field] IN AllowedViewForUser )將報表頁面上原有的View Module參數(shù)切片器其“字段”綁定從原來的View Module[View Module]更改為這個新的FilteredViewParameter[View Module]。設(shè)置默認(rèn)視圖在頁面加載時我們希望自動選中用戶有權(quán)限的第一個視圖。可以設(shè)置一個度量值作為切片器的默認(rèn)值但更簡單的方式是確保FilteredViewParameter表中用戶有權(quán)訪問的視圖選項只有一個那么切片器會自動選中它如果有多個則可以在頁面加載時通過書簽來設(shè)置默認(rèn)選擇。4.4 方案二的優(yōu)缺點與適用場景優(yōu)點體驗流暢所有操作在一個頁面內(nèi)完成無需跳轉(zhuǎn)用戶體驗連貫。狀態(tài)保持頁面上的其他篩選器如時間、地區(qū)在切換視圖時得以保留因為數(shù)據(jù)上下文沒有因頁面跳轉(zhuǎn)而重置。維護相對集中所有視覺對象都在一個頁面便于統(tǒng)一設(shè)計和格式調(diào)整。缺點頁面布局復(fù)雜需要精心設(shè)計頁面布局避免不同視圖的視覺對象相互重疊管理起來可能比多個獨立頁面更麻煩。邏輯稍顯復(fù)雜涉及字段參數(shù)、條件格式、動態(tài)表過濾等多重技術(shù)對開發(fā)者的要求較高。性能考量即使某些視覺對象被隱藏只要其數(shù)據(jù)存在于模型中它們?nèi)匀豢赡茉诤笈_參與查詢。如果隱藏的視覺對象非常復(fù)雜可能會對性能有輕微影響。適用場景非常適合內(nèi)容模塊化、結(jié)構(gòu)清晰、且不同權(quán)限用戶所需信息存在重疊或遞進關(guān)系的報表。例如一個數(shù)據(jù)分析詳情頁初級用戶看匯總圖表高級用戶可以選擇下鉆看到明細(xì)表格和關(guān)聯(lián)分析。5. 權(quán)限同步與部署實戰(zhàn)要點無論采用哪種方案將開發(fā)好的報表部署到Power BI服務(wù)并確保權(quán)限生效是最后也是至關(guān)重要的一步。5.1 數(shù)據(jù)源身份驗證與動態(tài)行級安全性的誤區(qū)在Power BI服務(wù)配置數(shù)據(jù)集時你會看到“動態(tài)行級安全性”選項。請注意我們這里討論的非DAX頁面權(quán)限方案通常不依賴或不需要啟用這個功能。動態(tài)RLS是針對DAX RLS規(guī)則的。我們的權(quán)限映射表PagePermission或UserViewMapping是作為報表數(shù)據(jù)的一部分加載的其篩選依賴于報表內(nèi)部的度量值如CurrentUser和計算表。因此在設(shè)置數(shù)據(jù)源憑據(jù)時重點確保用于刷新權(quán)限映射表的數(shù)據(jù)源如SQL數(shù)據(jù)庫、SharePoint其認(rèn)證方式如OAuth2、服務(wù)主體能夠成功執(zhí)行刷新即可。報表的最終消費者在查看報表時使用的是其自身的Power BI身份在“設(shè)置”-“管理權(quán)限”中分配報表內(nèi)部邏輯會基于此身份進行權(quán)限判斷。5.2 部署流程與測試 checklist發(fā)布報表將Power BI Desktop文件.pbix發(fā)布到Power BI服務(wù)的工作區(qū)。配置數(shù)據(jù)集計劃刷新如果權(quán)限映射表來自外部數(shù)據(jù)源強烈推薦必須在服務(wù)端為數(shù)據(jù)集配置定時刷新如每日以確保用戶權(quán)限變更能同步到報表。實操心得對于權(quán)限表即使數(shù)據(jù)量小也建議設(shè)置刷新??梢允褂肞ower Automate或API調(diào)用在權(quán)限系統(tǒng)變更時觸發(fā)數(shù)據(jù)集的即時刷新實現(xiàn)權(quán)限的準(zhǔn)實時生效。分配工作區(qū)訪問權(quán)限在Power BI服務(wù)的工作區(qū)中將需要查看報表的用戶或組添加為“成員”、“貢獻者”或“查看者”。至少需要“查看者”角色才能打開報表。終極測試使用不同賬號測試這是最可靠的測試方法。如果條件允許在Azure AD或Office 365中創(chuàng)建測試用戶或用同事的賬號進行測試。測試“無權(quán)限”場景確保一個沒有任何頁面權(quán)限的用戶登錄后看到的是友好的提示如方案一中的提示信息或一個空白的導(dǎo)航頁而不是報錯或顯示未授權(quán)的數(shù)據(jù)。測試邊緣情況例如用戶同時屬于多個角色權(quán)限表中有重復(fù)記錄等確保報表邏輯穩(wěn)定不會出現(xiàn)按鈕重復(fù)或視圖錯亂。檢查性能在頁面元素較多、權(quán)限邏輯復(fù)雜時留意報表的加載和交互速度。5.3 方案組合與擴展思路在實際項目中純頁面導(dǎo)航或純單頁視圖往往不能滿足所有需求。我們可以將方案進行組合層級權(quán)限使用動態(tài)導(dǎo)航菜單方案一作為一級門戶將用戶引導(dǎo)到幾個大的功能模塊如“銷售報表”、“財務(wù)報表”。在每個功能模塊內(nèi)部再使用單頁多視圖方案二來控制同一模塊下不同詳細(xì)程度的頁面內(nèi)容。元素級權(quán)限即使在同一頁面內(nèi)除了整組圖表的切換還可以對單個視覺對象如一個包含敏感信息的表格、甚至一個圖表中的特定數(shù)據(jù)點通過條件格式進行更精細(xì)的權(quán)限控制。其核心邏輯是一致的利用一個根據(jù)當(dāng)前用戶身份計算出的TRUE/FALSE標(biāo)志來控制視覺對象格式窗格中的“可見性”、“條件格式”等屬性。最后需要明確的是非DAX的權(quán)限控制方案其安全性建立在Power BI報表本身的安全訪問之上。即用戶必須首先有權(quán)訪問這個Power BI報表文件在工作區(qū)中擁有權(quán)限。在此前提下我們實現(xiàn)的是一種應(yīng)用層級的、增強型的用戶體驗控制。它無法替代Power BI平臺級的RLS對于底層數(shù)據(jù)的行級安全保護。對于涉及核心敏感數(shù)據(jù)如個人薪資、客戶隱私信息的場景仍然需要甚至必須結(jié)合DAX RLS來構(gòu)建從數(shù)據(jù)到展示的完整安全防線。而我們今天探討的這些方法則是在此防線之上讓報表用起來更順手、更符合業(yè)務(wù)流程的“智能導(dǎo)航系統(tǒng)”。