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