2017年3月14日
#
組織樹報(bào)表中由id與父id來實(shí)現(xiàn)組織樹報(bào)表,若層級數(shù)較多時(shí),對每個(gè)單元格設(shè)置過濾條件和形態(tài)會(huì)比較繁瑣,因此FineReport提供了一種特殊的數(shù)據(jù)集——樹數(shù)據(jù)集,只需要簡單的設(shè)置就能自動(dòng)遞歸出層級,方便的實(shí)現(xiàn)如下圖組織樹報(bào)表:
圖一

圖二

構(gòu)建樹
新建工作薄,添加數(shù)據(jù)集ds1取出原始數(shù)據(jù),SQL語句為SELECT * FROM 公司部門。
1)根據(jù)父字段構(gòu)建樹
使用情形:原始表結(jié)構(gòu)中符合ID、parentID結(jié)構(gòu),我們可以通過父ID這個(gè)字段生成樹,添加樹數(shù)據(jù)集,如下圖:


2)根據(jù)數(shù)據(jù)長度構(gòu)建樹
使用情形:原始表結(jié)構(gòu)中所有ID都在一列中,且沒有父ID字段,但是ID是有規(guī)律的,每組的長度相同,且子級的前N位就是父級編號,添加樹數(shù)據(jù)集,如下圖:


預(yù)覽樹數(shù)據(jù)集,可看到已自動(dòng)生成遞歸樹數(shù)據(jù),F(xiàn)R_GEN_0為最高層,依次往下,如下:

縱向組織樹編輯
按照下圖所示將對應(yīng)的數(shù)據(jù)列拖入到單元格中,并將A2單元格的左父格設(shè)置為A1,A3單元格的左父格設(shè)置為A2:

有上面預(yù)覽數(shù)據(jù)可以看到從二層FR_GEN_1開始,就會(huì)有空白數(shù)據(jù),這是因?yàn)閿?shù)據(jù)庫中存儲的數(shù)據(jù)有上一級部門本身的部門名稱和部門ID,其上一級部門的部門級數(shù)會(huì)低一級,比如說上述數(shù)據(jù)的第一行為總部,雖然總部下面有子部門,但是數(shù)據(jù)庫中還是要存儲總部這個(gè)部門的部門名稱和部門ID的,總部對應(yīng)的級數(shù)為一級,那么其對應(yīng)的數(shù)據(jù)記錄行里面就只有FR_GEN_0層,下面的FR_GEN_1和FR_GEN_2這兩層就會(huì)沒有數(shù)據(jù),顯示為空白。
在模板制作過程中,從第二層級開始就會(huì)有空白數(shù)據(jù),需要將空白數(shù)據(jù)隱藏掉,選中A2和A3單元格,添加條件屬性,當(dāng)數(shù)據(jù)為空時(shí)隱藏該行,如下圖: 
如果組織結(jié)構(gòu)的層級結(jié)構(gòu)不確定,即有的層級有子層,有的層級沒有子層時(shí),其組織樹報(bào)表的實(shí)現(xiàn)方式請查看不規(guī)范組織樹報(bào)表
由于自動(dòng)生成的字段是編碼,可以使用數(shù)據(jù)字典將其轉(zhuǎn)為對應(yīng)的部門名稱,如下圖:
保存模板,點(diǎn)擊分頁預(yù)覽,效果如圖一。
橫向組織樹編輯
按照下圖所示將對應(yīng)的數(shù)據(jù)列拖入到單元格中,在右側(cè)單元格屬性表-擴(kuò)展屬性中將B1、C1單元格的擴(kuò)展方向設(shè)為橫向,
并將B1單元格的左父格設(shè)置為A1,C1單元格的左父格設(shè)置為B1:
有上面預(yù)覽數(shù)據(jù)可以看到從二層FR_GEN_1開始,就會(huì)有空白數(shù)據(jù),這是因?yàn)閿?shù)據(jù)庫中存儲的數(shù)據(jù)有上一級部門本身的部門名稱和部門ID,其上一級部門的部門級數(shù)會(huì)低一級,比如說上述數(shù)據(jù)的第一列為總部,雖然總部下面有子部門,但是數(shù)據(jù)庫中還是要存儲總部這個(gè)部門的部門名稱和部門ID的,總部對應(yīng)的級數(shù)為一級,那么其對應(yīng)的數(shù)據(jù)記錄列里面就只有FR_GEN_0層,下面的FR_GEN_1和FR_GEN_2這兩層就會(huì)沒有數(shù)據(jù),顯示為空白。
在模板制作過程中,從第二層級開始就會(huì)有空白數(shù)據(jù),需要將空白數(shù)據(jù)隱藏掉,選中B1和C1單元格,添加條件屬性,當(dāng)數(shù)據(jù)為空時(shí)隱藏該列,如下圖:

如果組織結(jié)構(gòu)的層級結(jié)構(gòu)不確定,即有的層級有子層,有的層級沒有子層時(shí),其組織樹報(bào)表的實(shí)現(xiàn)方式請查看不規(guī)則組織樹報(bào)表
由于自動(dòng)生成的字段是編碼,可以使用數(shù)據(jù)字典將其轉(zhuǎn)為對應(yīng)的部門名稱,如下圖:
保存模板,點(diǎn)擊分頁預(yù)覽,效果如圖二。
在企業(yè)應(yīng)用中,通常單個(gè)計(jì)算機(jī)的配置是有限的,而企業(yè)應(yīng)用又是高并發(fā)的需求,這個(gè)時(shí)候會(huì)通過計(jì)算機(jī)集群的方式來提高并發(fā)數(shù),從而提高整體應(yīng)用服務(wù)的性能。集群是將多臺計(jì)算機(jī)作為一個(gè)整體來提供相關(guān)應(yīng)用的服務(wù)。FineBI支持多計(jì)算機(jī)服務(wù)的集群部署,通過集群部署利用有限的計(jì)算機(jī)資源來有效提高整體應(yīng)用的并發(fā)性能。本文主要介紹整體FineBI集群的思路。
FineBI采用負(fù)載均衡集群的模式,將多臺服務(wù)器創(chuàng)建為一個(gè)集群服務(wù)器。這里碰到這幾個(gè)問題:1)web工程的存儲問題:FineBI在集群中,由于自身的問題需要多臺服務(wù)器讀取同一個(gè)web工程。因此要實(shí)現(xiàn)web工程分享。2)系統(tǒng)數(shù)據(jù)一致性:在FineBI的運(yùn)行過程中,存在讀寫的操作,同時(shí)有部分的數(shù)據(jù)的配置文件要寫入數(shù)據(jù)庫。需要保證集群的情況下,系統(tǒng)數(shù)據(jù)的一致性。3)負(fù)載均衡:一方面通過負(fù)載均衡來處理session的問題,另一方面達(dá)成負(fù)載均衡的集群環(huán)境,使用代理服務(wù)器可以將請求轉(zhuǎn)發(fā)給集群內(nèi)部的服務(wù)器,可以將負(fù)載均衡和代理服務(wù)器的高速緩存技術(shù)結(jié)合在一起,提供有益的性能。4)FS平臺集群:如FineBI使用FS平臺,則FS平臺的各種配置也需要進(jìn)行集群配置。
如下圖是一個(gè)FineBI進(jìn)去的架構(gòu)的案例示意圖,這種方式通過NFS文件共享來處理web工程。

Web工程存儲問題
Web工程的存儲,我們要解決的是多個(gè)服務(wù)器保證讀取同一個(gè)web工程。我們可以通過ceph做到多塊物理硬盤組件一塊邏輯硬盤,從而實(shí)現(xiàn)所有節(jié)點(diǎn)都是在訪問同一地址;也可以通過linux本身帶有的nfs共享文件服務(wù)來達(dá)成訪問同一web工程。無論使用哪一種方式,我們要保證:
<!--[if !supportLists]-->1)<!--[endif]-->訪問同一web工程
<!--[if !supportLists]-->2)<!--[endif]-->Cube存儲地址是一致的
因?yàn)橥粋€(gè)web工程下,要求cube的存儲地址是一致的,因此要求cube存儲地址一定要一樣。
而真正使用的時(shí)候,ceph的實(shí)現(xiàn)需要至少三臺計(jì)算機(jī)來實(shí)現(xiàn),而實(shí)際企業(yè)應(yīng)用中,比較少使用三臺;而nfs均可以且是linux本身的,因此使用“nfs”方案。
系統(tǒng)數(shù)據(jù)配置
單節(jié)點(diǎn)的情況下,利用緩存和通過操作系統(tǒng)的文件系統(tǒng)來保存數(shù)據(jù)的方式,在集群模式下不再合適。主要原因在于數(shù)據(jù)的一致性問題,多個(gè)節(jié)點(diǎn)可能進(jìn)行同時(shí)讀寫,更改系統(tǒng)數(shù)據(jù),最終勢必會(huì)造成整體數(shù)據(jù)不一致。最好的解決方案是系統(tǒng)配置數(shù)據(jù)全部交給MySQL等關(guān)系型數(shù)據(jù)庫來管理。但由于這樣工程量好大,更主要的原因?yàn)樵S多代碼缺少維護(hù),貿(mào)然更改可能帶來意想不到的bug。于是我們采用一種折中的做法。在集群中選出一臺幾點(diǎn)作為主節(jié)點(diǎn),簡稱M。其余節(jié)點(diǎn)擔(dān)當(dāng)子節(jié)點(diǎn),簡稱S。當(dāng)S上所有與更改系統(tǒng)配置相關(guān)的操作,全部發(fā)送到M上進(jìn)行處理。M負(fù)責(zé)來更改系統(tǒng)狀態(tài),維護(hù)整個(gè)系統(tǒng)到底一致的狀態(tài)。S節(jié)點(diǎn)放棄全部的緩存數(shù)據(jù),讀取狀態(tài)的時(shí)候,不再通過讀取自身數(shù)據(jù),而是通過向M發(fā)送讀取請求,獲得M上的數(shù)據(jù)。M節(jié)點(diǎn)自身可以存在緩存數(shù)據(jù)。其他數(shù)據(jù)S節(jié)點(diǎn)與M節(jié)點(diǎn)時(shí)等同的,不存在從屬關(guān)系。

因此按上述原由我們提供如下解決方案:
<!--[if !supportLists]-->1)<!--[endif]-->mysql數(shù)據(jù)庫:原web工程中存在finedb的配置信息轉(zhuǎn)存到mysql數(shù)據(jù)庫中。因?yàn)閒inedb數(shù)據(jù)庫只能有一個(gè)連接,無法多節(jié)點(diǎn)同時(shí)讀取,而mysql數(shù)據(jù)庫則不存在。Logdb也需遷移;
<!--[if !supportLists]-->2)<!--[endif]-->主子節(jié)點(diǎn):我們使用主子節(jié)點(diǎn)的方式來配置集群,系統(tǒng)數(shù)據(jù)的更改均在主節(jié)點(diǎn)上進(jìn)行,子節(jié)點(diǎn)只讀取主節(jié)點(diǎn)上的數(shù)據(jù);
<!--[if !supportLists]-->3)<!--[endif]-->Zookeeper:為了保證讀寫情況下,主子節(jié)點(diǎn)保證數(shù)據(jù)一致性,還需要zookeeper進(jìn)行通信,充當(dāng)文件鎖的功能。
負(fù)載均衡
在FineBI的集群環(huán)境中,我們可以使用任何支持負(fù)載均衡的服務(wù)器來完成輪發(fā)的任務(wù),并保證session粘滯。此處我們使用的是nginx反向代理,使用IP標(biāo)識輪發(fā),保證同一個(gè)用戶在同一個(gè)session。(在一個(gè)服務(wù)器一個(gè)節(jié)點(diǎn)的情況下,同一個(gè)IP就保證session粘滯)。
FS平臺集群
使用FS平臺集群插件,將FS平臺配置能夠滿足集群需求。在FS平臺集群中,F(xiàn)S平臺的所有操作都是發(fā)到主節(jié)點(diǎn)上來操作;子節(jié)點(diǎn)只是作計(jì)算服務(wù)器。
報(bào)表服務(wù)器
安裝釘釘管理插件后,打開報(bào)表管理平臺,管理系統(tǒng)下會(huì)增加釘釘管理節(jié)點(diǎn),釘釘相關(guān)的配置管理都將會(huì)放在這個(gè)節(jié)點(diǎn)中去配置:
同時(shí),設(shè)置定時(shí)任務(wù)的最后一步輸出設(shè)置中,會(huì)增加推送釘釘消息:
釘釘企業(yè)應(yīng)用
管理員登錄釘釘企業(yè)號,進(jìn)入微應(yīng)用設(shè)置,需要關(guān)注的信息有:
CorpID:是企業(yè)在釘釘中的標(biāo)識,每個(gè)企業(yè)擁有一個(gè)唯一的CorpID;
CorpSecret:是企業(yè)每個(gè)應(yīng)用的憑證密鑰
登錄FineReport管理平臺,點(diǎn)擊管理系統(tǒng)>釘釘管理節(jié)點(diǎn):將釘釘中的CorpID和CorpSecret分別填到釘釘企業(yè)號ID和管理組憑證密碼中,設(shè)置Token獲取路徑,可以自定義獲取的url,如果不寫則采用內(nèi)置的方式獲取,保存,如下圖:
釘釘提供的獲取token接口本身有缺陷:
1)釘釘提供的接口,使用corpid和secret獲取token,默認(rèn)不會(huì)緩存,但是釘釘提倡做token緩存,2小時(shí)內(nèi)可以重復(fù)使用,這樣減少對釘釘服務(wù)器的訪問,以免出現(xiàn)問題;
2)釘釘中集成多個(gè)應(yīng)用的話,如果多個(gè)應(yīng)用都會(huì)用到corpid和secret獲取token,如果某個(gè)應(yīng)用緩存了token,就會(huì)沖突
例如:應(yīng)用a,做了緩存,第一次訪問后獲取到token1,應(yīng)用b使用會(huì)重新取token2,此時(shí)應(yīng)用a還是用的token就無法訪問了。
針對這種情況,處理方式是所有應(yīng)用統(tǒng)一到一個(gè)地方去取token,此時(shí)需要設(shè)置自定義token的獲取地址
在釘釘插件中,釘釘管理>基本信息>設(shè)置Token獲取路徑,可以自定義獲取的url,如果不寫則采用內(nèi)置的方式獲取
Token獲取接口規(guī)則:返回json類型的數(shù)據(jù),{access_token:"xxxxx", jsapi_ticket:"xxxxx"}
釘釘管理后臺創(chuàng)建FineReport報(bào)表微應(yīng)用時(shí),例如http://www.finereporthelp.com:8181/app2/ReportServer?op=fs&corpid=$CORPID$,后面要加上參數(shù)&corpid=$CORPID$,這樣后臺會(huì)獲取到cropid,然后取到釘釘userid,做單點(diǎn)登錄;
- 釘釘用戶與報(bào)表用戶關(guān)聯(lián)
按照釘釘提供的方法,讀取釘釘通訊錄的成員,需要的字段有uesrid,name,department進(jìn)入FineReport報(bào)表管理平臺fs,點(diǎn)擊釘釘管理節(jié)點(diǎn),除了基本信息外,增加了釘釘成員管理,點(diǎn)擊效果如下:
表格中會(huì)自動(dòng)讀取釘釘企業(yè)號通訊錄中的所有成員,并且在每次打開該頁面時(shí)刷新為最新的;默認(rèn)釘釘成員與報(bào)表用戶相同,因?yàn)榇蟛糠智闆r下,釘釘成員名和報(bào)表用戶名是統(tǒng)一的;
如果您的釘釘成員名與報(bào)表用戶名是不一樣的,此時(shí),可以取消勾選釘釘成員與報(bào)表用戶相同設(shè)置,此時(shí)報(bào)表用戶名,可以將釘釘成員與報(bào)表用戶進(jìn)行關(guān)聯(lián),如下圖:
釘釘提供免登服務(wù),與微信類似,通過code可以獲取當(dāng)前取號的userid,獲取到userid后,通過關(guān)聯(lián)關(guān)系自動(dòng)登錄報(bào)表后臺
開發(fā)服務(wù)器可以主動(dòng)的發(fā)送消息給企業(yè)成員,比如使用FineReport定時(shí)器生成報(bào)表后,發(fā)送消息給相應(yīng)的人員進(jìn)行查看。進(jìn)入FineReport管理平臺,添加定時(shí)任務(wù):
到輸出設(shè)置這步,比如我們將定時(shí)生成的結(jié)果掛在其他這個(gè)目錄下面,并且命名為釘釘文檔測試:
通知與存檔選擇推送釘釘消息,企業(yè)應(yīng)用(AgentID)需要根據(jù)釘釘管理里的進(jìn)行填寫,例如下設(shè)置,這樣定時(shí)任務(wù)結(jié)束后,這個(gè)釘釘成員可以收到消息
定時(shí)生成結(jié)果的文件名:對應(yīng)發(fā)送消息的標(biāo)題名
企業(yè)應(yīng)用AgentID:發(fā)消息至哪個(gè)應(yīng)用
釘釘用戶:發(fā)消息給哪些成員,下拉框中會(huì)自動(dòng)讀取釘釘通訊錄中的所有成員,多個(gè)成員之間用|分割,比如Jane|Saber
部門ID:發(fā)消息給某個(gè)部門的所有成員,該屬性與釘釘用戶是并的關(guān)系,不同部門之間也用|分割
消息內(nèi)容:定義消息的正文內(nèi)容
定時(shí)結(jié)果訪問連接:勾選的話會(huì)在消息正文最后加上定時(shí)生成的結(jié)果連接,點(diǎn)擊后就可以直接打開定時(shí)結(jié)果;不選的話則只發(fā)送純文本消息。
定時(shí)任務(wù)設(shè)置好后,比如任務(wù)每天都會(huì)執(zhí)行,每次執(zhí)行后就會(huì)推送消息給對應(yīng)的成員,效果如下:
點(diǎn)擊連接,就可以看到定時(shí)生成的結(jié)果。