天天看點

基于 HTML5 WebGL 的 3D 倉儲管理系統

倉儲管理系統(WMS)是一個實時的計算機軟體系統,它能夠按照運作的業務規則和運算法則,對資訊、資源、行為、存貨和分銷運作進行更完美地管理,使其最大化滿足有效産出和精确性的要求。從财務軟體、進銷存軟體CIMS,從MRP、MRPII到ERP,代表了中國企業從粗放型管理走向集約管理的要求,競争的激烈和對成本的要求使得管理對象表現為:整和上遊、企業本身、下遊一體化供應鍊的資訊和資源。而倉庫,尤其是制造業中的倉庫,作為鍊上的節點,不同鍊節上的庫存觀不同,在物流供應鍊的管理中,不再把庫存作為維持生産和銷售的措施,而将其作為一種供應鍊的平衡機制,其作用主要是協調整個供應鍊。但現代企業同時又面臨着許多不确定因素,無論他們來自分供方還是來自生産或客戶,對企業來說處理好庫存管理與不确定性關系的唯一辦法是加強企業之間資訊的交流和共享,增加庫存決策資訊的透明性、可靠性和實時性。而這,正是WMS所要幫助企業解決的問題。

WMS軟體和進銷存管理軟體的最大差別在于:進銷存軟體的目标是針對于特定對象(如倉庫)的商品、單據流動,是對于倉庫作業結果的記錄、核對和管理——報警、報表、結果分析,比如記錄商品出入庫的時間、經手人等;而WMS軟體則除了管理倉庫作業的結果記錄、核對和管理外最大的功能是對倉庫作業過程的指導和規範:即不但對結果進行處理,更是通過對作業動作的指導和規範保證作業的準确性、速度和相關記錄資料的自動登記(入計算機系統),增加倉庫的效率、管理透明度、真實度降低成本比如通過無線終端指導操作員給某定單發貨:當操作員提出發貨請求時,終端提示操作員應到哪個具體的倉庫貨位取出指定數量的那幾種商品,掃描貨架和商品條碼核對是否正确,然後送到接貨區,錄入運輸機關資訊,完成出貨任務,重要的是包括出貨時間、操作員、貨物種類、數量、産品序列号、承運機關等資訊在貨物裝車的同時已經通過無線方式傳輸到了計算機資訊中心資料庫。

由于市場需求量較大,我們來好好解析今天這個例子。

動圖如下:

基于 HTML5 WebGL 的 3D 倉儲管理系統

這個例子是采用 es6 的子產品化的方式部署的。打開 index.html 進入 lib/index.js,源碼是在 src 檔案夾中,我們直接進 src/view 下的 index.js 

基于 HTML5 WebGL 的 3D 倉儲管理系統

 在頂部加載其他子產品中含有 export 接口的子產品:

我們将頁面上的每個部分分開來放在不同的 js 檔案中,就是上面加載的 js export 的部分,根層容器 BorderLayout(整體最外層的 div),整張圖上的部分都是基于 borderLayout 的。

最外層容器 BorderLayout 是在 src/view/common 下的 BorderLayout.js 中自定義的類,其中 ht.Default.def(className, superClass, methods) 是 HT 中封裝的自定義類的函數,其中 className 為自定義類名, superClass 為要繼承的父類,methods 為方法和變量聲明,要使用這個方法要先在外部定義這個函數變量,通過 functionName.superClass.constructor.call(this) 方法繼承。BorderLayout 自定義類繼承了 ht.ui.drawable.BorderLayout 布局元件,此布局器将自身空間劃分為上、下、左、右、中間五個區域,每個區域可以放置一個子元件。為了能正常互動,重寫 getSplitterAt 函數将 splitterRect 的寬度修改為 10,以及為了調整左側 splitterCanvas 的尺寸,以便擋住子元件而重寫的 layoutSplitterCanvas 兩個方法:

左側欄 sidebar,分為 8 個部分:頂部 logo、貨位統計表格、進度條、分割線、貨物表格、圖表、管理組、問題回報按鈕等。

基于 HTML5 WebGL 的 3D 倉儲管理系統

可以檢視 src/view 下的 sidebar.js 檔案,這個 js 檔案中同樣加載了  src/view/common 下的TreeHoverBackgroundDrawable.js 和 ProgressBarSelectBarDrawable.js 中的  TreeHoverBackgroundDrawable 和 ProgressBarSelectBarDrawable 變量,以及 src/controller 下的 sidebar.js 中的 controller 變量:

HT 封裝了一個 ht.ui.VBoxLayout 函數,用來将子元件放置在同一垂直列中,我們可以将左側欄要顯示的部分都放到這個元件中,這樣所有的部分都是以垂直列排布:

頂部 logo 是根據在 Label 标簽上添加 icon 的方法來實作的,并将這個 topLabel 添加進垂直列 vBoxLayout 中:

對于“貨位統計表格”,我們采用的是 HT 封裝的 TreeTableView 元件,以樹和表格的組合方式呈現 DataModel 中資料元素屬性及父子關系,并将這個“樹表”添加進垂直列 vBoxLayout 中:

我們在設定“行選中”時背景傳入了一個 TreeHoverBackgroundDrawable 對象,這個對象是在 src\view\common 下的 TreeHoverBackgroundDrawable.js 檔案中定義的,其中 ht.Default.def(className, superClass, methods) 是 HT 中封裝的自定義類的函數,其中 className 為自定義類名, superClass 為要繼承的父類,methods 為方法和變量聲明,要使用這個方法要先在外部定義這個函數變量,通過 functionName.superClass.constructor.call(this) 方法繼承。TreeHoverBackgroundDrawable 自定義類繼承了 ht.ui.drawable.Drawable 元件用于繪制元件背景、圖示等,隻重寫了 draw 和 getSerializableProperties 兩個方法,我們在 draw 方法中重繪了 shelfTreeTable 的行選中背景色,并重載了  getSerializableProperties 序列化元件函數,并将 TreeHoverBackgroundDrawable 傳入的參數作為 map 中新添加的屬性:

記住要導出 TreeHoverBackgroundDrawable :

HT 還封裝了非常好用的 ht.ui.ProgressBar 元件,可直接繪制進度條:

我們在 設定“前景”的時候傳入了一個 ProgressBarSelectBarDrawable 對象,這個對象在 src\view\common 下的 ProgressBarSelectBarDrawable.js 中定義的。具體定義方法跟上面的 TreeHoverBackgroundDrawable 函數對象類似,這裡不再贅述。

分割線的制作最為簡單,隻要将一個矩形的高度設定為 1 即可,我們用 ht.ui.View() 元件來制作:

貨物表格的操作幾乎和貨位統計表格相同,這裡不再贅述。

我們将一個 json 的圖表檔案當做圖檔傳給圖表的元件容器作為背景,也能很輕松地操作:

管理組和頂部 logo 的定義方式類似,這裡不再贅述。

問題回報按鈕,我們将這個部分用 HT 封裝的 ht.ui.Button 元件來制作,并将這個部分添加進垂直列 vBoxLayout 中:

基于 HTML5 WebGL 的 3D 倉儲管理系統

視圖部分做好了,在子產品化開發中,controller 就是做互動的部分,shelfTreeTable 貨位統計表格, cargoTreeTable 貨物表格, feedbackButton 問題回報按鈕, progressBar  進度條四個部分的互動都是在在 src/controller 下的 sidebar.js 中定義的。通過 findViewById(id, recursive) 根據id查找子元件,recursive 表示是否遞歸查找。

shelfTreeTable 貨位統計表格的資料綁定傳輸方式與 cargoTreeTable 貨物表格類似,這裡我們隻對 shelfTreeTable 貨位統計表格的資料綁定進行解析。shelfTreeTable 一共有三列,其中不同的部分隻有“已用”和“剩餘”兩個部分,是以我們隻要将這兩個部分進行資料綁定即可,先建立兩列:

接着周遊 json 檔案,将 json 檔案中對應的 used、remain以及 labelColors 通過 set/getAttr 或 簡寫 a 的方式進行資料綁定:

最後在 controller 函數對象中調用 這個函數:

progressBar 進度條的變化是通過設定定時器改變 progressBar 的 value 值來動态改變的:

feedbackButton 問題回報按鈕,通過增加 View 事件監聽器來監聽按鈕的點選事件:

右側根容器 splitLayout

基于 HTML5 WebGL 的 3D 倉儲管理系統

直接用的分割元件 ht.ui.SplitLayout 進行分割布局:

右側頭部 header

基于 HTML5 WebGL 的 3D 倉儲管理系統

這個 header 是從 src/view 下的 header.js 中擷取的對象,為 ht.ui.RelativeLayout 相對定位布局器,分為 5 個部分:searchField 搜尋框、titleLabel 主标題、temperatureLabel1 溫度、humidityLabel1 濕度以及 airpressureLabel1 氣壓。

這裡我們沒有對“搜尋框” searchField 進行資料綁定,以及搜尋的功能,這隻是一個樣例,不涉及業務部分:

對于 titleLabel 主标題比較簡單,和溫度、濕度以及氣壓類似,我就隻說明一下主标題 titleLabel 的定義:

然後互動部分在 src/controller 下的 header.js 中做了右鍵點選出現菜單欄以及單擊 titleLabel 的位置出現下拉菜單兩種互動,通過控制滑鼠的點選事件來控制事件的互動:

右側下部分 RelativeLayout 相對布局器(相對于右側下部分最根層 div),包含中間顯示 3d 部分 graph3dView、輕按兩下貨櫃或貨物才會出現的 shelfPane、以及出現在右下角的圖表 chartPane,将這三部分添加進 RelativeLayout 相對布局容器:

基于 HTML5 WebGL 的 3D 倉儲管理系統

然後将右側相對布局器 relativeLayout 和右側頭部 header 添加進右側底部容器 splitLayout:

再将左側部分的 sidebar 和右側部分的所有也就是 splitLayout 添加進整個底部容器 borderLayout,再将底部容器添加進 html body 體中:

 我們具體說說這個相對布局器内部包含的 3d 部分 graph3dView、輕按兩下貨櫃或貨物才會出現的 shelfPane、以及出現在右下角的圖表 chartPane。

(1) graph3dView

從 src\view\3d 檔案夾中的 index.js 中擷取 graph3dView 的外部接口被 src/view 中的 index.js 調用:

基于 HTML5 WebGL 的 3D 倉儲管理系統

從這個 3d 場景中可以看到,我們需要“地闆”、“牆面”、“貨架”、“叉車”、“貨物”以及 3d 場景。

在 3d 檔案夾下的 index.js 中,我們從檔案夾中導入所有需要的接口:

g3d.js 檔案中隻設定了場景以及對部分事件的監聽:

我們在 G.js 中定義了一些基礎資料,其他引用的 js 中都會反複調用這些變量,是以我們先來解析這個檔案:

裡面有三個函數,分别是“貨架的 obj 分解”、“加載模型”、“随機配置設定貨物的類型”:

 這個 3d 場景中還有不可缺少的“貨物”和“貨架”以及“叉車”,三者的定義方式類似,這裡隻對“貨架”進行解釋。我們直接在“貨物”的 js 中引入底下的“托盤”的 js 檔案,将它們看做一個整體:

在 src\view\3d\cargo.js 檔案中,定義了一個“貨物”類,這個類中聲明了很多方法,比較基礎,有需要的自己可以檢視這個檔案,這裡我不過多解釋。主要講一下如何加載這個“貨物”的 obj,我們在 G.js 檔案中有定義一個 loadObj 函數,我們在代碼頂部也有引入,導入 obj 檔案之後就在“貨物”的庫存增加這個“貨物”:

牆和地闆也是比較簡單的,簡單地繼承 ht.Node 和 ht.Shape,這裡以“牆”進行解釋,繼承之後直接在構造函數中進行屬性的設定即可:

floor、wall、shelf 以及 car 這四個類都準備完畢,隻需要在 src\view\3d\index.js 中 new 一個新的對象并加入到資料模型 dataModel 中即可,這裡隻展示 car “叉車”的初始化代碼:

至于“貨物”,我們在這個 js 上是采用定時器調用 in 和 out 方法,這裡有一個模拟的資料庫 interfaces.js 檔案,有需求的可以看一下,這裡我們隻當資料來調用(進出庫和上下架類似,這裡隻展示進出庫的設定方法):

(2) shelfPane

從 src\view\common 檔案夾中的 shelfPane.js 中擷取 graph3dView 的外部接口被 src/view 中的 index.js 調用:

基于 HTML5 WebGL 的 3D 倉儲管理系統

shelfPane 是基于 Pane 類的,在 shelfPane.js 檔案中引入這個類和事件派發器:

Pane 類繼承于 HT 封裝的 ht.ui.TabLayout 類, 并做了一些特定的屬性設定:

我們這個例子中的“資訊”清單是一個表格元件,HT 通過 ht.ui.TableLayout 函數定義一個表格,然後通過 ht.ui.TableRow 向表格中添加行,這個例子中的“備注”、“編号”、“來源”、“入庫”、“發往”以及“出庫”都是文本框,這裡拿“備注”作為舉例:

“歸類”和“模型”類似,都是下拉框,我們用 HT 封裝的 ht.ui.ComboBox 組合框元件,跟 ht.ui.TextField 也是異曲同工,隻是具體操作不同而已,HT 這樣做使用上更簡便更容易上手,這裡我們以“模型”進行解析,在設定“下拉資料”的時候我們利用了 HT 中的資料綁定:

最後一個“染色”,HT 封裝了 ht.ui.ColorPicker 顔色選擇器元件,元件從 ht.ui.ComboBox 繼承并使用 ht.ui.ColorDropDown 作為下拉模闆,跟上面的下拉清單很類似,隻是下拉的模闆變了而已:

最後通過 ht.ui.Form 元件的 addChangeListener 事件監聽函數監聽 JSON 整體變化事件和 JSON 中單條資料變化事件,這兩種事件的解釋如下圖:

基于 HTML5 WebGL 的 3D 倉儲管理系統

具體監聽方法如下:

然後通過 HT 封裝的事件派發器 ht.Notifier 将界面中不同區域的元件之間通過事件派發進行互動,根據不同的事件類型進行不同的動作:

(3) chartPane

 從 src\view\common 檔案夾中的 chartPane.js 中擷取 graph3dView 的外部接口被 src/view 中的 index.js 調用:

基于 HTML5 WebGL 的 3D 倉儲管理系統

回到正題,chartPane 圖表面闆的實作非常容易,将内部的子元件設定背景圖檔再添加進 chartPane 圖表面闆中即可:

我的部落格即将同步至騰訊雲+社群,邀請大家一同入駐。

繼續閱讀