今天聊:BI 儀表盤及數據導出技術難點分析

前端早早聊大會,與掘金聯合舉辦。加 codingdreamer 進大會技術羣,贏在新的起跑線。html


第二十九屆|前端數據可視化專場,高強度一次性洞察可視化的前端玩法,7-17 全天直播,9 位講師,報名上車👉 ):前端

image.png

全部往期都有全程錄播,上手年票一次性解鎖所有react


正文以下

本文是第十五屆 - 前端早早聊報表專場,也是早早聊第 109 場,來自 字節 - Jerry 的分享。git

1、開場

簡單的自我介紹

Hello 你們好,我是來自字節跳動商業產品客增大前端團隊的前端工程師 Jerry,很榮幸今天能表明團隊向你們一塊兒分享咱們最近的一些業務實踐,由於咱們如今恰好在作一款商業 BI 系統,因此適逢今天的主題,我將爲你們帶來一場 title 爲《如何實現商業報表的儀表盤及導出分享功能》的技術沉澱。github

字節跳動最「掙錢」的前端團隊

首先先介紹一下咱們的團隊:咱們是一個已經有百號人的前端團隊,咱們的同窗也遍及在北京、上海、杭州以及北美這些地方,這些城市都有咱們的 base,咱們在作的事情,是致力於提供互聯網商業變現的最佳解決方案踐行「信息創造價值」理念web

在這裏,你將對接字節跳動百億流量的全產品矩陣,見證公司全新業務線的孵化成長,支撐公司千億規模的收入增加。在這裏的每一分每一秒,你都能親身感覺到字節跳動的蓬勃生機。雖然咱們是業務團隊,但咱們也在作不少與時俱進的技術建設,其中包括有:前端現代化工程化體系升級、Node 能力探索、一鍵式 CD 工具、組件服務化、前端國際化通用解決方案、可視化頁面搭建系統、商業智能 BI 系統、前端自動化 E2E 測試、面向將來的微前端設計模式等等。面試

在支撐業務不斷演進的過程當中咱們嘗試不斷探索技術賦能業務的更優實踐。而且在分享的最後也有咱們的福利環節噢,我將爲你們獻上我們團隊的內推綠色通道,若是你們聽完個人分享,以爲咱們在作的事情頗有趣,你對此感興趣,那就歡迎快來投遞喲。數據庫

好吧,那題外話我們就很少說啦。在咱們正式開始今天分享以前,首先須要感謝下咱們的組織同窗。辛苦咱們的主持人花花幫咱們暖場,也感謝 Scott 提供了這樣一個讓我與你們可以一塊兒交流的機會。那咱們如今開始直奔我們的主題吧。canvas

分享大綱

這是我們今天分享的大綱:我會逐步帶着你們切入我們要開發一個報表系統的幾個核心細節,帶着你們從業務實際需求場景入手,一步步完成一個前端商業報表系統的搭建。其實我今天準備了五十多頁的 PPT,由於作一個 BI 系統有太多有意思或者說值得去講的東西了,我很但願把全部的都分享給你們,但由於時間關係,我可能只能抽出其中一部分,所以我儘量讓它們能更加通俗易懂,而且我會更多地專一在前端的一些主要功能的實現思路,固然一個 BI 系統確定遠遠不止這些。整個分享的過程或許會比較漫長,但願今天來聽個人分享的同窗,聽完以後也都能有所收穫。後端

因此我們今天的分享主要有如下幾個部分:

  • 大數據時代下的前端商業分析方案
  • 定製化數據分析能力的實現
  • 儀表板製做
  • 大數據分享及處處
  • 對業務更深的思考與對將來的展望

那如今,開始咱們第一個主題吧。

2、大數據時代下的前端商業分析方案

大時代的趨勢

做爲作互聯網的咱們,其實對過去幾十年的歷史進程都歷歷在目。首先,20 世紀的前十年,是 PC 端的時代,各種門戶網站的崛起,也啓蒙了現代的許多互聯網巨頭;過去的十年,是移動端的時代,各路諸侯都在爭奪互聯網的戰場,最終的贏家,奠基了現現在的互聯網格局。而如今,是數據的時代,由於不少時候,大量的數據或是強大的數據分析能力,可以成爲一家公司的核心競爭力。所以,數據是這個時代最核心的資源。如今不管是 B 端仍是 C 端的團隊,都會有大量的數據積累,例如咱們平時常見的頁面埋點、PV、UV,亦或是一些業務數據,都如同一座座數據金礦,等待咱們去發掘其中價值。

業務的實際場景

而咱們,剛好在作這樣一件事情。由於咱們是商業化大部門下的團隊,因此在咱們的大部門中,沉澱了不少有意義有價值的數據,好比咱們的一些銷售業績、或者是一些客戶數據。爲此,在咱們的部門下,也聘請了不少專業的數據分析師同窗,亦或是銷售本身,平時可能都會作一些報表、週報,用以彙總數據,觀察趨勢,就以下面的這張圖所示,左側的日報圖,就是咱們業務中實際產出的報表,咱們的同窗可能會作一些日報類的報表,用以披露部門內的一些銷售業績動態。他們會本身經過 Excel 等工具,在拿到數據後本身繪製各類各樣的圖表,而後像這樣組裝起來,再發送出去。而右側的報表圖,就是咱們的同窗使用了咱們研發的系統後,本身組裝完成的報表,效果也符合他們的預期。

業內的競品

並且這樣的業務場景實際上是一件很常見的事,並非說只在字節存在,就像咱們剛剛提到的,在現在的時代大背景下,每家公司沉澱出了大量待發掘的數據已是一件再普通不過的事情了,所以,也有不少公司發現了這樣的商機,在業內也作出了不少成熟的產品。好比比較有名的 Tableau,雖然它已經開始逐步放棄中國市場了,可是功能和交互,也值得不少系統參考,國內也有不少很給力的產品,像阿里的 QuickBI,由於做爲雲服務的提供方,BI 類系統的產生能夠說是再正常不過了。

咱們爲何要作這樣一件事?

那業內已經有這麼多成熟的產品了,爲何咱們還須要作這樣重複的事情呢?咱們是在重複造輪子嗎?

其實主要是處於如下四點緣由:

  • 部門內現存大量有價值的數據:剛剛咱們提到,由於咱們是商業化部門,所以有大量的營銷類數據沉澱也是一件再正常不過的事情了。
  • 大量重複性的報表工做:剛剛咱們提到,其實咱們的銷售同窗,或者數據分析師,都是下載了數據以後,本身經過 Excel 或者其餘工具繪製好圖表,而後製做成報表,並且周而復始,每次發週報,或者雙月總結,都要不斷重複作一樣的事情。咱們但願能幫助他們,提供能力自動化幫他們完成一些重複的工做。
  • 須要有特定的數據權限管控: 衆所周知,其實數據在公司內是很敏感的,對於數據的權限也是須要嚴格管控的。傳統的模式,用戶直接講數據下載走以後,數據的流向以及最後的分發,咱們都沒法追蹤,這實際上是一件頗有風險的事情,咱們但願藉助咱們商業化現有的鑑權體系,對咱們的數據加以更嚴格的管控。
  • 咱們但願用戶在一個系統裏,就能作完全部事:咱們不但願就是用戶還得在咱們的系統裏面下數據,而後切換到 Excel 裏面去拼裝數據,而後又獲得另外一個系統裏面去發週報,咱們但願能讓用戶,在咱們本身研發的一個系統裏,就能完成他們平時工做中的全部事情。

咱們該怎麼作?

根據咱們剛剛的分析,其實用戶每週的工做,主要就是如下三個核心的流程:製做他們所須要的每一張圖表 -> 將這些圖表組裝成儀表板 -> 最終將這張圖表以週報的形式分享出去,或者定時用以給本身回溯。順着這樣一套流程和思路,咱們開始來逐步分析每個階段都須要哪些功能模塊,而且又有哪些技術選型可以幫助咱們實現。

3、定製化數據分析能力實現

接下來來看業務流程的第一個環節,也是一份報表最核心的組成單元 —— 圖表。那圖表從哪來呢,天然,咱們須要爲用戶提供圖表的生產能力,也就是咱們的定製化數據分析能力。

用戶需求分析

那用戶指望的效果又是怎麼樣的呢?參考業內的系統實現,用戶其實根本不須要關心背後繁雜的 SQL 邏輯來知足本身的數據查詢,也不用本身繪製圖表,只須要經過簡單的經過一些拖拖拽拽,就像咱們圖中的動圖所示,好比說拖拽一些咱們提供好的數據字段,咱們就能夠快速地查詢出這樣的一個他所想要的數據,或者說是快速地幫他繪製出來一張圖表,而後用戶也能夠自由地選擇圖表的類型,好比說想要作成一個折線圖,或者是咱們普通的這樣一個 Table 樣的交叉表。

技術體系梳理

因此要實現一個定製化的數據分析能力,咱們大概須要哪些功能點去支撐呢?這裏咱們總體能夠分爲以下這幾部分:

好比剛剛一下就映入眼簾的拖拽能力,這也是市面上的競品作的比較常見的一個能力,咱們能夠藉助像 react-dnd 這樣的優秀的開源實踐,來幫助咱們去實現這樣一個能力。

第二點的話是用戶可能不會知足於咱們提供好的一些默認字段,像好比說咱們能夠看到系統左側這部分的字段 List,可能這些字段並不能知足用戶他實際的更復雜的數據分析場景,用戶可能須要本身來生產一些這樣的一個字段表達式,其中可能包含像求和、求平均等一系列複雜的計算操做,可以讓有更加定製化的能力。因此爲了讓功能更加定製化,咱們也會提供自定義字段(或者更形象點說就是自定義查詢查詢表達式)的能力。

固然咱們的這樣一個定製化的分析的頁面,核心確定仍是咱們的圖表展現。咱們能夠基於 antd 的 Table,去實現 Table 類型的像好比交叉表這類的數據呈現,而且咱們可使用 ECharts,來實現像圖表類的數據呈現。 咱們能夠選擇 Mobx 做爲數據流支撐,由於它很「靈活」,至於爲何,我們來看下面這張圖:

咱們將剛纔頁面其實能夠作一下相似圖中各部分的功能拆分。首先是咱們左側的這樣一個字段拖拽的 List,用戶能夠從這邊去把字段拖入到像咱們剛纔看到這樣的一個有行、列、數值分類的一個個容器裏面,這部分的區域咱們就叫他分析區,由於他是用來產出可用於後端查詢的一個字段分析配置。藉助 Mbox 的 Autorun 能力,當分析區配置變化以後,會自動觸發後端查詢獲取到對應的圖表數據,交給咱們底部的面積比較大的核心圖標展現區,用於展現咱們繪製後的圖表。

不只如此,咱們還能夠看到在頁面的右側還有這樣一個側邊欄,提供給用戶選擇圖表類型的這樣一個能力,還有一些讓用戶可以自由定製化圖表樣式像好比說什麼開啓或關閉合並單格,或者是添加一些表格樣式,好比隔行變色這樣一些比較常見的能力。當配置改變以後,能夠經過 Mbox 的 Observer 機制自動去更新一些圖表的元數據或者狀態,觸發圖表的從新渲染。

那梳理完清晰架構設計以後,咱們就開始去逐個去擊破吧

字段拖拽

首先來看咱們最開始說到的字段拖拽能力。前端如何實現一個拖拽功能呢?瞭解過這方面的同窗確定會想到好比 HTML 原生的 drag 事件等等。固然,咱們也能借助一些工具庫幫咱們快速完成,好比咱們系統中使用的 react-dnd,就是很不錯的選擇。

回到主題,咱們想要實現一個拖拽能力,核心就是把握住 PPT 上的拖拽三要素,由於不論你的業務邏輯是什麼樣,這三個要素始終是你全部功能的基點:

  • 拖拽環境(DragDropContext):相似於咱們平時包裹數據流的時候都須要用到的 Provider,可以爲它的全部子元素提供這樣一個拖拽底層支持的全局上下文;
  • 拖拽項(DragSource):就是咱們實際拖拽的東西,好比你們剛剛看到的一個個字段;
  • 放置容器(DropTarget):咱們拖拽的東西確定不能一直拖着吧,它確定須要被放到某個地方去,那這個地方就是咱們所說的放置容器。

那要如何用實際的代碼邏輯實現拖拽三要素呢?咱們能夠藉助 react-dnd 爲咱們提供的 DragSource 和 DragTarget 方法,對咱們的組件進行包裝便可,咱們只要定義好可拖拽的類型、拖拽事件的回調、亦或是咱們想要自定義的能力,好比圖中所述,咱們對拖拽中的元素會賦予特定的樣式 —— 透明度增大,就能完成一個拖拽要素的封裝。

而且,咱們將重複的流程封裝了高階組件(由於咱們的項目在啓動時,react-hooks 還只是剛火起來的提案),這樣 當咱們要快速包裝組件的時候,一切是否是變得簡單了許多呢:

這樣一來,咱們想要爲系統中的哪一個元素賦予一些拖拽能力,只須要包裹一個裝飾器就 OK 啦。這樣的工具函數,就能實現咱們的拖拽能力「隨時插拔,隨處複用」。

而且細心的同窗可能會發現,咱們的字段實際上是有不一樣的類型,分析區內也有不一樣的位置,而且顧名思義,像行、列這些分析區,在交叉表內天然是不一樣的邏輯或者呈現,舉一個比較簡單例子,像好比說咱們把日期類的這樣一個字段拖入到過濾器裏面,它應該呈現的是一個像日曆這樣的一個組件,而後咱們把一些維度類的字段拖入到過濾器裏面,它可能展現的就是一個向下拉枚舉或者說是一個搜索框的這樣一個組件呈現。

咱們能夠用不少判斷去堆砌,但怎樣才能更優雅地去維護這塊的邏輯呢?其實細心的同窗可能發現了,咱們將字段拖入分析區的結果,實際上是一個二維的過程,它取決於字段的類型和拖拽終點的類型,所以咱們使用一個矩陣來表述這樣的過程,矩陣最終的求值,就對應着不一樣狀況下,咱們所需的組件和配置。好比咱們右側這樣一個示例代碼,咱們把日期類這樣一個字段,去拖入到咱們這樣的一個行中,它就映射到了咱們這樣的一個矩陣中的 date 字段下的第一項,而後這個配置就是對應着字段最終要產生的組件,還有它數據初始化元信息或者說一系列的配置信息。

這樣一來,咱們後面想要維護這樣的一份配置,配合上直觀的註釋,其實就很簡單了,像好比咱們如今想要加一些什麼分析區的配置,其實就只要在矩陣裏面去額外的去增長一些項目就能夠了。

自定義計算表達式

有了字段拖拽以後,用戶並不知足於咱們提供的默認字段,不少時候,用戶都但願本身能有自定義字段表達式的能力。咱們可能不會讓用戶完整去寫複雜的 SQL,咱們但願這個系統可以更加簡易,可以下降門檻服務於更多的用戶,所以咱們有了自定義的語法結構,好比由咱們提供的函數和字段,用戶就能夠快速地組裝好一個表達式,正如咱們圖中的動圖所示。

藉助 CodeMirror,咱們很快就能實現這樣的能力。

首先,CodeMirror 可以爲咱們提供很是優秀的關鍵字高亮能力。瞭解過編譯原理的同窗必定知道,對於一段字符串的解析過程,會分爲詞法解析和語法解析等幾個步驟,在這裏,CodeMirror 爲咱們提供了在詞法解析的環節,咱們能夠定製化處理關鍵字的能力,咱們能夠拋出每一個 token 對應的類型,CodeMirror 就會爲咱們指定的關鍵字賦予特定的 class,咱們就能爲其定製想要的樣式:

不只如此,CodeMirror 還支持讓咱們自定義語法提示菜單。咱們只要準備好待提示的 List,在用戶輸入或者粘貼的時候,filter 好 list 餵給 CodeMirror 就好了。藉助每一個 list item 的 render 方法,咱們還能夠自由定製下拉菜單裏的樣式,開發起來起來就像使用 Echarts 或者 Antd 這樣的組件庫同樣溫馨。

這裏有一個小技巧,其實自動補全後光標是位於補全文案的最後的,對於函數類的文案,咱們可能會更但願它的光標是落在函數的括號 ( ) 裏,所以當咱們檢測到用戶在經過自動補全鍵入函數的時候,手動操做移動光標,將它移動到括號內:

圖表渲染

有了字段,天然就能夠從後端查詢數據啦。那對於前端來講,咱們最終要渲染的是如圖所示的這樣一張交叉表,很明顯咱們須要的是結構化的數據,然後端直接將字段經過 SELECT 查詢出來的結果數據必定是鋪平的,從接口響應到數據渲染,必然會須要有個數據格式化的過程。那這個過程誰去完成呢,若是前端來作,對服務器性能更友好,後端就不須要關注數據格式化,能夠專一在數據分析而查詢,而若是後端來作,對我更友好,哈哈,開個小玩笑。固然,確定是極致的性能更爲重要。那數據格式化咱們有怎樣的思路呢?

咱們能夠對數據圖表進行細化,若是要渲染一個單元格的數據,那麼這個數據單元格必定會有一個惟一的座標,座標從哪來呢?其實就是他的行列字段所組成的數據索引。咱們能夠封裝一個數據處理器,就是咱們圖中的 Processor,對後端給到的數據 list 進行結構化,變成更加直觀的 DataMap。

咱們能夠看到,通過格式化以後的 DataMap 裏,一級的 Key,就對應着 DataSource 裏的一行數據,而二級的 Key,就對應着當前數據所在的列,這樣每個單元格的數據,均可以經過這樣的「座標」被明確表示出來,當咱們再拿着這個 DataMap 去生成 Antd 的 DataSource 和 Columns 時,一切是否是就清晰明朗多了。其實這個過程就是一個再普通不過的樹生成邏輯,咱們部門面試常考題噢哈哈劃重點

至於 Echarts 相關的圖表,今天我就不作過多介紹啦,我相信前端早早聊大會以前的數據可視化專場已經有不少類 似的議題啦。

終於搞定了咱們的圖表來源了,接下來就是我們系統的核心,組裝圖表。

4、儀表板製做

爲何咱們要把一張張圖表組裝起來呢?

由於:多張圖表組合產生的價值必定大於全部圖表單張價值的總和。多張圖表去作一個協同分析或者作一個數據關聯的話,確定是可以迸發出更多的價值。

那用戶實際須要的,又是怎樣的呢?

用戶需求分析

用戶在業務中去製做的這樣的一個報表,也就是像咱們下方的圖示,報表中會披露一些指標,會有一些圖,其實就是我們前一步作好的那些圖表,同時也會有一些這樣一個文案總結,好比總結一下部門或者說團隊這個月去有沒有什麼上升的趨勢。

而要支撐起一個儀表板功能,咱們須要哪些部分呢?

儀表板技術架構

從下而上,咱們可使用這些技術爲儀表板提供能力支撐。儀表板中會有一些原子組件組成儀表板的必要元素,好比咱們剛剛作完的圖表,還有一些富文本卡片,或者說是一些圖片組件,固然也有在儀表板中很常見的全局篩選器,用以讓用戶全量地去過濾一些數據。

有了原子組件以後,咱們也但願能賦予用戶拖拽佈局的能力,讓用戶能夠在系統中自由組裝這些原子組件,而後產出一份能讓他本身滿意的報表。

梳理清晰了技術體系,那咱們就自下而上逐步攻堅吧。

富文本能力實現

原子組件裏,比較有挑戰的,應該就算是富文本編輯器了,這個曾經做爲前端三大難題的技術點,現在優秀的前端社區已經爲咱們準備好了成熟的解決方案 —— Quill,它不只能幫助咱們快速實現富文本編輯功能,還可以讓咱們自由地自定義各項能力,這相比於其餘的工具而言是更優秀的。

好比咱們能夠自定義工具欄的內容。咱們能夠經過自由組裝 HTML 標籤的形式,自定義富文本工具欄的呈現。好比 說 Button 元素,它最終在這樣一個工具欄中渲染出來的就是一個按鈕,好比說咱們這樣的一個加粗功能的按鈕,或者是一個添加下劃線的功能按鈕。而後像有一些下拉菜單這樣的功能,咱們能夠經過 select 配合 option 快速實現,好比選擇字體字號,這也是一個比較經常使用的實現。

不只如此,咱們還能夠爲 Quill 增長一些自定義的功能,好比 Quill 默認只支持四種字號,因此咱們也能賦予它定製化字號:

得益於 Quill 靈活的定製化能力,咱們能接下不少 PM 給到的各式各樣的定製化需求。

拖拽佈局能力

有了儀表板的基本元素以後,咱們就能夠開始關注自定義佈局的實現了。其實社區已經有一款特別好的實現了,就是咱們的使用的 react-grid-layout,能夠看它官方提供的 demo,其實效果就已經足夠知足咱們的需求了。

不過這裏有一個小優化,你們也能夠關注一下。就是官方提供了一個自適應寬度的能力,可是它本質是監聽了window 的 resize 事件,而後你們剛剛若是有注意的話,其實咱們的系統是有一個可伸縮的側邊欄的,因此當咱們去伸縮側邊欄的時候,這個儀表板它不會去適配這樣一個寬度。所以咱們能夠藉助 react-resize-detector 對他進行一個擴展,簡單優化一下官方的這個小痛點。

爲了讓數據管理更加清晰,咱們將佈局和數據的渲染邏輯拆分開來,有單獨的配置維護佈局數據,另外一份配置維護組件元數據。因此儀表板整理的佈局流程就是相似圖中所示:首先咱們真正存在後端的,就是一份完整的儀表板數據,像好比說它裏面有哪些組件,而且有怎樣的佈局。而後前端系統經過請求拉到這樣的一個數據信息以後,咱們會作一個解析,咱們會把這樣的佈局信息映射到每個對應的組件上。最終這些綁定了佈局信息的各個原子組件,通過咱們的佈局器佈局,最終呈現出來的就是用戶自由組裝的美觀的儀表板啦。

全局篩選器

全局篩選器對於一份 BI 儀表板而言是再常見不過的一個功能了,不少時候,咱們都會提供一個儀表板層面的篩選器,供給用戶自定義篩選數據的能力。篩選器能夠與任一圖表相關聯,而且這些篩選項也只會對關聯的圖表生效。

這裏咱們就舉一個形象一點的例子(下圖)。好比在咱們的儀表板中有三個篩選器,篩選器 123,而後他們分別關聯了不一樣的圖表,篩選器 1 關聯了圖表 1,篩選器 2 關聯了圖表 1 和圖表 2,篩選器 3 關聯了圖表 2,天然,當咱們操做篩選器 1 的時候,只有圖表 1 會刷新,操做篩選器 2 的時候,圖表 1 和圖表 2 都須要刷新,而操做圖表 3 的時候,也只能有圖表 2 刷新。

那這樣的邏輯又要如何用技術實現呢?整理的流程就像咱們圖中所示,咱們能夠在 Store 裏去統一收集全部的篩選器,篩選器上都會有一個字段標明關聯的圖表的信息,當篩選器發生變化時,就會自動更新咱們的 Store,Store 會自動觸發篩選器的生成器,針對不一樣的圖表生成不一樣的篩選項,圖表再根據不一樣的篩選項去向後端請求數據。

這樣一來,一個儀表板的核心骨架功能基本就已經搭建完成了,你們能夠看看咱們儀表板的最終使用效果。

但其實咱們尚未完成全部的事情。

5、大數據分享及導出

首先有一點咱們須要明確,那就是:用戶製做的報表,必定是但願它能被帶到更多系統以外的地方去展示。由於用戶製做的報表,確定不是本身作着玩的,或者本身欣賞它的「美」,更多的時候,他確定是但願拿着這樣的一份報表去發週報,或者是或者說去作這樣的一個數據分析結果的彙報。

所以,可以將數據導出或者分享,也是一個 BI 系統不可或缺的能力。

數據分享的形態

數據的導出分享,其實能夠概括爲如下三種形態:

  • 連接分享:好比用戶直接 copy 了瀏覽器地址欄裏的系統連接,或者是咱們的頁面裏有個按鈕叫作相似「複製連接」,用戶點擊如下,就能自動把圖表的連接複製到剪切板中,這樣就能將他本身作的圖表或者報表直接分享出去;
  • 圖表導出:用戶可能但願本身作的圖表或者報表,可以導出成一張圖片或者 Excel 文件,這樣在他須要發送郵件或者消息的時候,就能更加直觀;
  • 週報訂閱:一個比較智能的系統,確定不會說讓用戶每週或者每次他須要的時候,來系統裏截個圖,才能把它的報表分享出去,咱們徹底能夠作的更智能化,好比說把這樣一個流程作的更加自動,用戶只須要快速配置,咱們就能夠定時地爲用戶去推送他所須要的報表信息,好比截圖、連接等等。

連接分享

咱們先來看分享的第一種形態 —— 連接分享。用戶點擊 Button 以後,就能把內容自動複製到剪切板。其實這也是一個比較常見的實現,咱們只要建立好一個 input 標籤,將須要複製的內容填充到裏面,執行 input.select() 選中全部的內容,再經過瀏覽器提供的 document.execCommand('copy'),就能把對應的內容複製到剪切板中啦。這樣的邏輯,咱們也能夠封裝成經常使用的工具函數,用於其餘場景下的複用。

圖表導出

對於圖表導出的話,咱們須要先掌握前端下載能力的實現。若是前端想要讓用戶下載一個文件的話,其實要作的事情很簡單,就是建立一個 a 標籤,它支持咱們爲 href 賦予 Blob 這樣的 ObjectURL,而且再爲它賦予一個 download 屬性用來表示下載後的文件的文件名,這樣咱們只須要執行一下這個 a 標籤的 click 操做,就能模擬出用戶下載文件啦。

對於咱們的文件而言,比較常見的就是一個 file string,圖片類型的,大部分也能夠導出一個 base64,咱們均可以封裝好工具函數,將他們轉化成 Blob 對象。最終讓用戶可以靈活地完成下載。

有了前端下載能力的支持,就能夠針對不一樣的文件進行定製化的處理。對於頁面上的 Table 類元素,用戶可能更但願的是導出一份所見即所得的 Excel 文件,咱們能夠藉助 js-xlsx,它爲咱們提供了一個方法叫作 table_to_sheet,只須要傳入一個咱們頁面中的 table HTML 元素,這個工具就會自動幫咱們解析成 Excel 文件格式的數據,而且也會保留咱們頁面中的合併單元格等樣式,最後生成一段 file string,咱們直接就能使用剛剛提到的文件下載能力,將文件導出啦。

而對於圖表類型的圖表,熟悉 canvas 的同窗可能就會比較親切了,canvas 提供了一個名叫 toDataURL 的 API,可以快速將 canvas 內的內容導出一份 base64 數據。而對於一些非 canvas 的元素,好比咱們的指標卡圖表,他可能就是一個純粹的 Card,咱們也可使用 html2canvas 快速將它變成一張圖片。

週報訂閱

剛纔咱們還說到一點,咱們還能夠把報表的導出流程作的更加自動化,用戶沒必要要每次須要報表的時候再來咱們的 BI 系統裏生成一份報表導出,咱們能夠提供讓用戶自由配置的能力,好比用戶選好何時須要爲它推送報表,或者說是按期給某些人,系統就會自動去定時爲用戶推送報表。

最終一個形式化其實就是相似於咱們右邊這張圖的呈現。若是用戶訂閱好了一份報表,系統就會定時地在飛書上爲它推送這樣一條消息,其中就包含了用戶製做的報表的一個截圖,而後還有一個報表對應的連接。

而後若是要實現這樣一個訂閱能力的話,若是你們有了解過 Linux 的話,就會知道 crontab 這樣的一個實現定時能力的命令,總體的思路其實就是藉助這樣的能力去支撐,咱們公司爲咱們封裝好了這樣的一個能力,咱們稱它爲 cronjob,而後用戶他若是建立了一個訂閱任務以後,咱們就能夠把它寫到咱們的定時調度數據庫裏面,接下來去建立這樣一個定時任務,當觸發的時機到了的時候,咱們就能夠藉助無頭瀏覽器,相似業內比較成熟的 puppteer,自動打開報表爲咱們的用戶去作報表的截圖,最終再將截圖帶着咱們的一些報表信息推送給用戶。

6、對業務更深地思考與將來的展望

其實在整個業務的迭代演進過程當中,咱們的 BI 系統也有了一個更深的思考,並且咱們也但願對將來有更遠的展望。其實咱們是更但願如今 BI 系統可以成爲一個更靈活的數據中臺,不僅僅去服務於業務,像好比咱們如今已經實現的能力,若是別的業務想要複用咱們系統製做的報表,他直接經過 iframe 的形式將咱們系統內的報表嵌入到他們的系統中。而且咱們將來也但願能借助像微前端這樣的能力,讓咱們系統中的報表,亦或是一些圖表組件,可以不侷限於咱們的開發框架,也能快速地被其餘系統更靈活地複用。

數據中臺的真正意義不僅僅是業務上的可複用性咱們也會不斷探索技術上的可複用能力

因此對咱們而言:一切還只是開始,將來仍存挑戰。咱們後面還有微前端、移動端、大屏展現等等能力想要去作,咱們也相信,很快咱們也能作到,因此對咱們所作的事情感興趣的小夥伴,快快加入咱們吧,我們一塊兒去作有挑戰的事。

7、總結

因此咱們再總體回顧一下咱們剛剛講完的內容,咱們也能夠藉助業內優秀的實踐做爲咱們的技術底層實現,快速支撐起咱們的報表系統的技術選型和基建,再將各類各樣的技術抽象成通用的能力封裝,創造出咱們的定製化數據分析能力(提供了圖表來源)、儀表板原子組件(提供儀表板的必要組成元素)以及數據導出分享能力(支持 BI 系統的必要功能),最終再將咱們所擁有的資源進行整合封裝,就產出了咱們提供給用戶的定製化報表解決方案。

8、福利環節

書籍推薦

而後前端早早聊有一個慣例,就是每次分享的嘉賓都須要分享一本書,這裏我推薦的就是這本《The Grammar Of Graphics》,當時 D3.js 的做者,就是看完了這本書以後,有了靈感,寫出了 d3.js 這麼優秀的框架。但其實我更想表達的,就是在 BI 系統的這段歷程下來,我更深入地理解到:作一個商業分析系統最重要的事不是攻克哪些技術難點而是要善於去發現數據的價值用技術爲數據賦予生命。所以我以爲這本書,再合適不過了。

這裏我也想要表達一下我對團隊的感謝,一個系統的搭建,確定不是一我的就能完美完成的,在這裏我不只要特別感謝一路來和我一同奮鬥的同事們,這些成果是你們共同努力的結晶,咱們也但願將來還能有更多的同窗可以參與進來,由於就像咱們剛剛說的,咱們作的都還只是開始,咱們還要作的事情還有不少,咱們須要你。

​ 前端路漫漫,與君共勉,你們對於大廠選拔標準有任何疑問,均可以在評論區留言,我都會回覆,或者加我也行(codingdream),還能夠圍觀我朋友圈。


別忘了第二十九屆|前端數據可視化專場,7-17 全天直播,報名上車👉 ):

相關文章
相關標籤/搜索