出于國家安全考慮,現(xiàn)在換流站監(jiān)控系統(tǒng)要求運行在Linux系統(tǒng)上?,F(xiàn)有的客戶端/服務(wù)器(client/server, C/S)類專用報表組件如水晶報表等都是運行在Windows系統(tǒng)上的,在Linux上無法使用。在Linux上雖然有Open Office等辦公套件,但是由于Linux上沒有類似Windows上的對象連接與嵌入技術(shù)(object linking and embedding, OLE)的對象嵌入機制,所以也無法利用這些辦公套件開發(fā)報表。
雖然現(xiàn)有的瀏覽器/服務(wù)器(browser/server, B/S)類報表組件可以運行在Linux系統(tǒng)上,但是使用B/S類報表,需要部署Web服務(wù)器。而變電站監(jiān)控系統(tǒng)屬于一區(qū)系統(tǒng),按照二次安防要求,不能采用Web服務(wù)。因此,無法使用B/S類報表組件。故此,開發(fā)可以在Linux系統(tǒng)使用的C/S報表組件,勢在必行。
本文提供了基于QtWebEngine模塊,利用Web技術(shù)的報表組件開發(fā)方案。此方案既利用了Web頁面的強大展示能力,又通過QtWebEngine與Web頁面的交互能力避開了搭建Web服務(wù)器的需要,從而構(gòu)建了一套強大靈活的C/S報表組件。以下對此技術(shù)方案的技術(shù)環(huán)節(jié)進行闡述。
QtWebEngine是Qt框架中的一個瀏覽器模塊,它提供了易于使用且可擴展的應(yīng)用程序接口(appli- cation programming interface, API)。利用QtWebEngine可以很容易地把Web內(nèi)容嵌入到Qt應(yīng)用程序中。QtWebEngine不允許C++/Qt代碼直接操作頁面元素。然而,QtWebEngine提供了RunJavaScript方法??梢酝ㄟ^該方法調(diào)用Web頁面的JavaScript腳本,并獲取執(zhí)行結(jié)果,從而獲取和調(diào)整頁面內(nèi)容。
QtWebEngine支持Web技術(shù)中最新的超文本標記語言(hyper text markup language, HTML)第五版標準。HTML5提供了一套拖放接口,使Web應(yīng)用能夠支持拖放功能。通過這些功能,用戶可以使用鼠標選擇可拖動元素,并將元素拖動到可放置容器,通過釋放鼠標按鈕來放置這些元素。
開發(fā)者可以自定義能夠成為可拖拽的元素類型、可拖拽元素產(chǎn)生的反饋,以及可放置的容器元素?;贖TML5的拖放接口,可以實現(xiàn)報表的可視化設(shè)計。此外,Web技術(shù)中的高性能數(shù)據(jù)圖表和數(shù)據(jù)表格也是報表開發(fā)中必需的功能。
報表模板文件的本質(zhì)是一個基于JavaScript對象表示法(Java script object notation, JSON)格式的文本文件,其內(nèi)部保存了數(shù)據(jù)源和界面部件信息兩部分數(shù)據(jù)。
2.1 數(shù)據(jù)源
數(shù)據(jù)源保存的并非真正在報表中使用的數(shù)據(jù),而是報表要使用的數(shù)據(jù)點的編號和名稱信息。當(dāng)用戶查看報表時,查看器會根據(jù)數(shù)據(jù)源中的數(shù)據(jù)點編號和用戶選擇的時間段,動態(tài)生成一個以數(shù)據(jù)點編號為列,以時間點為行的表格。這才是報表要使用的數(shù)據(jù)。數(shù)據(jù)源在報表模板中以JSON數(shù)組形式存儲,如圖1所示。
圖1 數(shù)據(jù)源JSON結(jié)構(gòu)
每個數(shù)組元素是一個JSON對象,對象內(nèi)部由兩個鍵值對組成,id代表數(shù)據(jù)點的編號,name代表數(shù)據(jù)點名稱。
2.2 界面部件信息
報表界面部件信息包含了報表界面部件的布局關(guān)系和每個部件自身的屬性設(shè)置。界面部件的布局關(guān)系可以用一個樹形的結(jié)構(gòu)表示,如圖2所示。
整個報表作為根節(jié)點;在報表頂層的部件為第一級子節(jié)點;其中的容器類型節(jié)點可以擁有自己的子節(jié)點,容器類型節(jié)點可以嵌套。報表組件在展示報表時可以遞歸遍歷這個樹形結(jié)構(gòu)來創(chuàng)建組件對象。
這個樹形結(jié)構(gòu)在報表模板中用嵌套的JSON對象來存儲,如圖3所示。
圖2 界面部件布局關(guān)系
圖3 界面部件信息JSON結(jié)構(gòu)
界面部件的結(jié)構(gòu)定義如下:1)type,組件類型;2)id,組件編號;3)options,組件屬性;4)list,組件的子節(jié)點列表。
加載報表模板文件后,設(shè)計器和查看器可以根據(jù)部件的type獲取對應(yīng)的類型,創(chuàng)建部件實例。在設(shè)計階段,設(shè)計器可以通過部件id定位部件對象,以便更新部件屬性設(shè)置和調(diào)整部件位置。
報表組件分為設(shè)計器與查看器兩個部分。設(shè)計器用于創(chuàng)建和編輯報表,由監(jiān)控系統(tǒng)工程開發(fā)人員使用;查看器給運行人員使用,用于在線展示報表內(nèi)容。設(shè)計器與查看器是相互獨立的,但是在底層通過報表模板的格式定義相互影響,共享部分設(shè)計。
3.1 設(shè)計器
設(shè)計器內(nèi)部的組件關(guān)系如圖4所示。
圖4 報表設(shè)計器組件關(guān)系
由圖4可以看出,Web頁面內(nèi)的主要組件有Widgets-list、Type-list、Report-from、Properties-editor、DataSource-editor和Store。
Widgets-list是一個提供了包含所有報表部件占位符的列表組件;Type-list是非可視化組件,提供了報表部件的類型定義;創(chuàng)建組件的時候,需要獲取對應(yīng)的組件類型,比如數(shù)據(jù)表格、數(shù)據(jù)圖表,所以需要一個組件的類型映射表,根據(jù)組件的type獲取對應(yīng)的類型,創(chuàng)建實例。
Report-form代表了報表表單。Widgets-list內(nèi)的部件占位符都被賦予HTML中的draggable屬性,這樣可以將部件占位符從Widgets-list拖到Report- form上。當(dāng)一個部件占位符被從Widgets-list拖拽走時,Widgets-list會創(chuàng)建該占位符的一個復(fù)制品,供下次使用。
Report-form組件監(jiān)聽了drop事件。當(dāng)部件占位符被拖到Report-form上時,會觸發(fā)監(jiān)測的drop事件。Report-form組件的事件處理器可以從事件參數(shù)中獲取部件占位符,并提取出其攜帶的部件類型信息。然后Widget-builder根據(jù)部件類型信息從Type- lis獲取完整的部件定義,并創(chuàng)建相應(yīng)的部件實例。
Store組件管理數(shù)據(jù)源定義、報表結(jié)構(gòu)信息、報表組件屬性等內(nèi)容。DataSource-editor組件用于編輯修改數(shù)據(jù)源定義。
Properties-editor組件用于編輯修改報表組件的屬性,Store組件與Properties-editor組件、Report- form組件都是雙向交互的。在Properties-editor組件中修改了組件屬性,Store中的內(nèi)容會相應(yīng)改變,并且會改變Report-form中報表的顯示。在Report-form中修改了報表的部件或布局時,Store中的信息會相應(yīng)改變,在Properties-editor組件上顯示的內(nèi)容也會跟隨變動。
報表設(shè)計器的Qt部分加載報表模板或創(chuàng)建一個內(nèi)容為空的報表模板后,會執(zhí)行RunJavaScript方法來調(diào)用Web側(cè)的LoadReportTpl方法,將模板文件傳遞給Web側(cè)。Web側(cè)將報表模板解析后,先存入Store組件,然后由Report-form組件構(gòu)建相應(yīng)的報表部件并顯示。
用戶隨后可以通過可視化方式對報表模板進行編輯,如配置數(shù)據(jù)源、添加修改圖表/表格、設(shè)置圖表/表格的關(guān)聯(lián)數(shù)據(jù)點等。用戶編輯完模板后,可以點擊Qt側(cè)的保存按鈕,然后Qt側(cè)執(zhí)行RunJavaScript方法調(diào)用Web側(cè)的SaveReportTpl方法,從Web側(cè)獲取報表模板。
3.2 查看器
查看器內(nèi)部結(jié)構(gòu)的組件關(guān)系如圖5所示。
圖5 報表查看器組件關(guān)系
由圖5可以看出,查看器Web頁面內(nèi)的主要組件有Type-list、Report-from和Store。查看器內(nèi)的組件與設(shè)計器內(nèi)同名組件的功能基本相同。不同之處在于,Store組件和Report-from的交互關(guān)系為單向。Web側(cè)將報表模板解析后,先存入Store組件,然后由Report-form組件構(gòu)建相應(yīng)的報表部件并顯示。Report-from不再對Store組件有影響。
查看器的組件關(guān)系相比設(shè)計器較為簡單。然而,其工作流程卻相對復(fù)雜。查看器的工作流程如圖6所示。
圖6 報表查看器工作流程
由圖6可以看出,報表查看器的工作流程如下:Qt部分負責(zé)加載報表模板;然后Qt側(cè)通過RunJavaScript方法調(diào)用Web側(cè)的LoadReportTpl方法,將報表模板文件傳遞給Web側(cè),由Web側(cè)顯示空的報表框架;同時Qt側(cè)對報表模板進行解析,提取出其中的數(shù)據(jù)源設(shè)置;然后Qt側(cè)根據(jù)解析出的數(shù)據(jù)源配置以及用戶設(shè)置的時間段從服務(wù)器獲取相應(yīng)時間端的數(shù)據(jù);Qt側(cè)通過RunJavaScript方法調(diào)用Web側(cè)的LoadDataSet方法,將報表要使用的數(shù)據(jù)集傳遞給Web側(cè);最后Web側(cè)用數(shù)據(jù)集填充報表框架,將報表渲染出來。
本文描述的報表組件開發(fā)方案,提供了可視化的報表設(shè)計工具,報表格式能夠靈活定義,而且能夠跨平臺使用,充分滿足變電站監(jiān)控系統(tǒng)的安防需求。并且,報表組件基于QtWebEngine和Web技術(shù)開發(fā),報表模板采用JSON格式定義,不依賴于第三方報表組件,具有良好的兼容性和通用性,易于應(yīng)用到其他C/S架構(gòu)的客戶端系統(tǒng)中。
本技術(shù)方案也可供使用其他非Qt框架的監(jiān)控系統(tǒng)做技術(shù)參考,只要使用的開發(fā)框架有可用的瀏覽器組件,即可采用類似的技術(shù)路線開發(fā)報表組件。