Warehouse management System (WMS) is a real-time computer software system that optimizes the management of information, resources, behavior, inventory and distribution operations according to operational business rules and algorithms to maximize efficient output and accuracy. From financial software, purchase, sale and inventory software CIMS, from MRP, MRPII to ERP, represent the requirements of Chinese enterprises from extensive management to intensive management. The fierce competition and the demand for cost make the object of management manifest as: integrating the information and resources of upstream, enterprise and downstream integrated supply chain. Warehouse, especially in the manufacturing industry, as the nodes on the chain, the view of inventory on different chain nodes is different. In the management of logistics supply chain, inventory is no longer regarded as a measure to maintain production and sales, but as a balance mechanism of supply chain, whose role is mainly to coordinate the whole supply chain. However, modern enterprises are faced with many uncertain factors at the same time, no matter they come from suppliers or from production or customers, the only way for enterprises to deal with the relationship between inventory management and uncertainty is to strengthen the exchange and sharing of information between enterprises, and increase the transparency, reliability and real-time inventory decision-making information. This is exactly what WMS is trying to help enterprises solve.

www.hightopo.com/demo/wareho…

Download.csdn.net/download/u0…

import sidebar from './sidebar.js';
import header from './header.js';
import BorderLayout from './common/BorderLayout.js';
import shelfPane from './common/shelfPane.js';
import chartPane from './common/chartPane.js';
import graph3dView from './3d/index';Copy the code

We split each part of the page into a separate JS file, the js export part loaded above, the root container BorderLayout (the outermost div of the whole), and the whole part of the image is based on the BorderLayout.

  • The outermost container, BorderLayout, is a custom class in borderLayout.js under SRC/View /common, Ht.default. def(className, superClass, methods) is the function of the user-defined class encapsulated in HT, where className is the name of the user-defined class and superClass is the parent class to be inherited. The methods for the method and the variable declarations, to use this method to outside the function variables, through the functionName.. SuperClass constructor. Call inheritance (this) method. BorderLayout custom class inherits the ht. The UI. The drawable. BorderLayout component layout, this layout editor’s own space is divided into the up, down, left, right, middle five regions, each region can be placed a child component. For normal interaction, rewrite the getSplitterAt function to change the width of splitterRect to 10, and rewrite the layoutSplitterCanvas method to resize the left splitterCanvas to block the child components:
let BorderLayout = function() { BorderLayout.superClass.constructor.call(this); this.setContinuous(true); this.setSplitterSize(0); }; Ht.default. def(BorderLayout, HT.ui.BorderLayout, {// Custom classes /** * splitter width is 0, for normal interaction, Override this function to change the width of splitterRect to 10 * @override */ getSplitterAt: Function (event) {var leftRect = this._leftSplitterRect, lp; if (leftRect) { leftRect = ht.Default.clone(leftRect); leftRect.width = 10; leftRect.x -= 5; if (event instanceof Event) lp = this.lp(event); else lp = event; if (ht.Default.containsPoint(leftRect, lp)) return 'left'; } return BorderLayout.superClass.getSplitterAt.call(this, event); }, /** * resize the left splitterCanvas to block the child component * @override */ layoutSplitterCanvas: function(canvas, x, y, width, height, region) { if (region === 'left') { canvas.style.pointerEvents = ''; canvas.style.display = 'block'; ht.Default.setCanvas(canvas, 10, height); canvas.style.left = this.getContentLeft() + this.tx() + x - 5 + 'px'; canvas.style.top = this.getContentTop() + this.ty() + y + 'px'; } else { BorderLayout.superClass.layoutSplitterCanvas.call(this, canvas, x, y, width, height, region); }}}); export default BorderLayout;Copy the code
  • Sidebar on the left side is divided into 8 parts: top logo, cargo position statistics form, progress bar, dividing line, cargo form, chart, management group, problem feedback button, etc.

           

Check out the sidebar. Js file under SRC /view, The same js files loaded under SRC/view/common TreeHoverBackgroundDrawable. Js and ProgressBarSelectBarDrawable in js TreeHoverBackgroundDrawable and ProgressBarSelectBarDrawable variables, and the sidebar under SRC/controller. The controller variables in js:

import TreeHoverBackgroundDrawable from './common/TreeHoverBackgroundDrawable.js'; import ProgressBarSelectBarDrawable from './common/ProgressBarSelectBarDrawable.js'; import controller from '.. /controller/sidebar.js';Copy the code

HT wraps a function called HT.ui. VBoxLayout to place all the components in the same vertical column. We can place all the left columns in this component so that all the components are in a vertical column:

let vBoxLayout = new ht.ui.VBoxLayout(); // This arranger places child components in the same vertical column; vBoxLayout.setBackground('#17191a');Copy the code

The top logo is implemented by adding an icon to the Label Label and adding the topLabel to the vertical column vBoxLayout:

let topLabel = new ht.ui.Label(); // Toplabel.settext (' demo-logo '); // Set the text toplabel.seticon ('imgs/logo.json'); Toplabel.seticonwidth (41); toplabel.setiConWidth (41); topLabel.setIconHeight(37); topLabel.setTextFont('18px arial, sans-serif'); topLabel.setTextColor('#fff'); topLabel.setPreferredSize(1, 64); // Toplabel.setBackground (' RGB (49,98,232)'); Vboxlayout. addView(topLabel, {// Add child component to container width: 'match_parent'// fill parent container});Copy the code

For the “cargo position statistics table”, we use the HT-encapsulated TreeTableView component to present the data element attributes and parent-child relationships in the DataModel as a combination of tree and table, and add the “tree table” to the vertical column vBoxLayout:

let shelfTreeTable = new ht.ui.TreeTableView(); // Tree table component, Appears in the combination of tree and tabular data element attribute and parent-child relationships in the DataModel shelfTreeTable. SetHoverBackgroundDrawable (new TreeHoverBackgroundDrawable (ceddf '# 1', 2)); / / set the hover state downward selected background Drawable object shelfTreeTable. SetSelectBackgroundDrawable (new TreeHoverBackgroundDrawable (ceddf '# 1', 2)); / line/set selected background Drawable object parameters for "background shelfTreeTable. SetBackground (null); shelfTreeTable.setIndent(20); / / setting different levels of indentation value shelfTreeTable setColumnLineVisible (false); . / / whether the column lines visible shelfTreeTable setRowLineVisible (false); shelfTreeTable.setExpandIcon('imgs/expand.json'); / / icon set, can be a color or picture etc shelfTreeTable. The setCollapseIcon (' imgs/collapse. Json); / / Settings icon in the merger, can be a color or picture etc shelfTreeTable. The setPreferredSizeRowCountLimit (); ShelfTreeTable. SetId ('shelfTreeTable'); // Set the number of rows to limit when calculating the preferredSize. Vboxlayout. addView(shelfTreeTable, {width: 'match_parent', height: 'wrap_content',// component's preferred height marginTop: 24, marginLeft: 4, marginRight: 4 });Copy the code

When we set the “line” selected background introduced into a TreeHoverBackgroundDrawable object, the object is in the SRC \ view \ TreeHoverBackgroundDrawable under common defined in js file, Ht.default. def(className, superClass, methods) is the function of the user-defined class encapsulated in HT, where className is the name of the user-defined class and superClass is the parent class to be inherited. The methods for the method and the variable declarations, to use this method to outside the function variables, through the functionName.. SuperClass constructor. Call inheritance (this) method. TreeHoverBackgroundDrawable custom class inherits the ht. The UI. The drawable. The drawable components used to draw the background, ICONS, etc., only rewrite the draw and getSerializableProperties two methods, We redraw the shelfTreeTable line in the draw method to select the background color, and reload the getSerializableProperties serialization component function, And TreeHoverBackgroundDrawable into the parameter as the map of newly added attributes:

let TreeHoverBackgroundDrawable = function(color, width) {
    TreeHoverBackgroundDrawable.superClass.constructor.call(this);
    this.setColor(color);
    this.setWidth(width);
};
ht.Default.def(TreeHoverBackgroundDrawable, ht.ui.drawable.Drawable, {
    ms_ac: ['color', 'width'],
    draw: function(x, y, width, height, data, view, dom) {
        var self = this,
            g = view.getRootContext(dom),
            color = self.getColor();
       
        g.beginPath();
        g.fillStyle = color;
        g.rect(x, y, self.getWidth(), height);
        g.fill();
    },
    getSerializableProperties: function() {
        var parentProperties = TreeHoverBackgroundDrawable.superClass.getSerializableProperties.call(this);
        return addMethod(parentProperties, {
            color: 1, width: 1
        });
    }
});Copy the code

Remember to export TreeHoverBackgroundDrawable:

export default TreeHoverBackgroundDrawable;Copy the code

HT also includes a very useful hT.ui.Progressbar component that allows you to draw progress bars directly:

let progressBar = new ht.ui.ProgressBar(); progressBar.setId('progressBar'); progressBar.setBackground('#3b2a00'); Progressbar.setbar ('rgba(0,0,0)'); // Set progressbar.setPADDING (5); // Set progressbar.setpadding (5); progressBar.setSelectBarDrawable(new ProgressBarSelectBarDrawable('#c58348', '#ffa866')); Progressbar.setvalue (40); // Set the Drawable object for progressbar.setValue (40); / / set the current progress value progressBar. SetBorderRadius (0); vBoxLayout.addView(progressBar, { marginTop: 24, width: 'match_parent', height: 28, marginBottom: 24, marginLeft: 14, marginRight: 14 });Copy the code

We set the “outlook” when introduced into a ProgressBarSelectBarDrawable object, the object under the SRC \ views \ common ProgressBarSelectBarDrawable. Js defined. Specific definition method above TreeHoverBackgroundDrawable function object, go here.

The easiest way to create a divider is to set the height of a rectangle to 1, using the hT.ui.view () component:

let separator = new ht.ui.View(); // The base class for all view components, from which all visual components must inherit separater.setBackground ('#666'); vBoxLayout.addView(separator, { width: 'match_parent', height: 1, marginLeft: 14, marginRight: 14, marginBottom: 24 });Copy the code

The operation of the cargo table is almost the same as that of the cargo position statistics table, which will not be described here.

We can also easily manipulate a JSON chart file as a picture passed to the chart component container as the background:

let chartView = new ht.ui.View();
chartView.setBackground('imgs/chart.json');
vBoxLayout.addView(chartView, {
    width: 173,
    height: 179,
    align: 'center',
    marginBottom: 10
});Copy the code

The management group and the top logo are defined in a similar way and will not be described here.

For the feedback Button, we made this part with hT.ui. Button component wrapped in HT, and added this part into the vertical column vBoxLayout:

let feedbackButton = new ht.ui.Button(); // Button class feedbackbutton. setId('feedbackButton'); Feedbackbutton.settext (' Problem feedback: [email protected]'); feedbackButton.setIcon('imgs/em.json'); feedbackButton.setTextColor('#fff'); feedbackButton.setHoverTextColor(shelfTreeTable.getHoverLabelColor()); / / set the text color feedbackButton hover condition. SetActiveTextColor (feedbackButton. GetHoverTextColor ()); / / set the active state text color feedbackButton setIconWidth (16); feedbackButton.setIconHeight(16); feedbackButton.setIconTextGap(10); feedbackButton.setAlign('left'); feedbackButton.setBackground(null); feedbackButton.setHoverBackground(null); feedbackButton.setActiveBackground(null); vBoxLayout.addView(feedbackButton, { width: 'match_parent', marginTop: 5, marginBottom: 10, marginLeft: 20 });Copy the code

The view part is done. In modular development, controller is the interactive part, shelfTreeTable inventory table, cargoTreeTable inventory table, feedbackButton problem feedbackButton, The interactions for all four sections of the progressBar progressBar are defined in sidebar.js under SRC /controller. FindViewById (id, recursive) is used to find subcomponents based on their ID, recursive indicating whether or not they are recursively searched.

ShelfTreeTable cargo table data binding transfer mode is similar to cargoTreeTable cargo table, here we only parse the data binding of shelfTreeTable cargo table. The shelfTreeTable has three columns, and the only different parts of the shelfTreeTable are the “used” and “remaining” parts, so we just need to bind these two parts to the data.

let column = new ht.ui.Column(); // Column data, used to define the column information of the table component column.setname ('used'); // Set the data element name column.setAccesstype ('attr'); SetAttr ('used'); setAttr('used', 98); setAttr('used', 98) column.setAlign('center'); columnModel.add(column); column = new ht.ui.Column(); column.setName('remain'); column.setAccessType('attr'); column.setWidth(65); column.setAlign('center'); columnModel.add(column);Copy the code

Then iterate over the JSON file and bind the corresponding Used, Remain, and labelColors in the JSON file with set/getAttr or short A:

for (var i = 0; i < json.length; i++) { var row = json[i]; Var data = new ht.data (); data.setIcon(row.icon); // Pass the icon in json data.setName(row.name); data.a('used', row.used); data.a('remain', row.remain); data.a('labelColors', row.colors); data.setIcon(row.icon); treeTable.dm().add(data); Var children = row.children; var children = row.children; if (children) { for (var j = 0; j < children.length; j++) { var child = children[j]; var childData = new ht.Data(); childData.setName(child.name); childData.setIcon(child.icon); childData.a('used', child.used); childData.a('remain', child.remain); childData.a('labelColors', child.colors); childData.setParent(data); treeTable.dm().add(childData); }}}Copy the code

Finally call this function in the Controller function object:

initTreeTableDatas(shelfTreeTable, json); / / json for.. Imported/model/shelf. JsonCopy the code

The progressBar progressBar is dynamically changed by setting a timer to change the value of the progressBar:

setInterval(() => {
    if (progressBar.getValue() >= 100) {
        progressBar.setValue(0);
    }
    progressBar.setValue(progressBar.getValue() + 1);
}, 50);Copy the code

FeedbackButton issue feedbackButton that listens for button clicks by adding a View event listener:

FeedbackButton. AddViewListener (e = > {the if (e.k ind = = = 'click') {/ / HT custom event attributes, specific viewHightopo.com/guide/guide...window.location.href = "mailto:[email protected]"; }});Copy the code
  • The right root container splitLayout

          

Ht.ui.SplitLayout:

let splitLayout = new ht.ui.SplitLayout(); / / this layout, its space is divided into upper and lower two area or left and right two regions, each region can be placed a child component splitLayout. SetSplitterVisible (false); splitLayout.setPositionType('absoluteFirst'); splitLayout.setOrientation('v');Copy the code
  • Right header header

        

This header is an object obtained from header.js under SRC /view. It is a RelativeLayout layout for HT.ui. SearchField Search box, titleLabel title, temperatureLabel1 temperature, humidityLabel1 humidity, and airpressureLabel1 airpressure.

Here we do not have the “search box” searchField data binding, and search capabilities, this is just a sample, not involved in the business part:

let searchField = new ht.ui.TextField(); Searchfield.setborder (new ht.ui.border.LineBorder(1, '#d8d8d8')); / / in the component of the canvas. Draw a straight line border searchField setBorderRadius (12); searchField.setBackground(null); searchField.setIcon('imgs/search.json'); searchField.setIconPosition('left'); searchField.setPadding([2, 16, 2, 16]); searchField.setColor('rgb(138, 138, 138)'); searchField.setPlaceholder('Find everything... '); searchField.getView().className = 'search'; header.addView(searchField, { width: 180, marginLeft: 20, vAlign: 'middle' });Copy the code

The main title of titleLabel is relatively simple, similar to temperature, humidity and air pressure. I will just explain the definition of the main title titleLabel:

let titleLabel = new ht.ui.Label(); // Titlelabel.setid ('title'); titleLabel.setIcon('imgs/expand.json'); titleLabel.setTextColor('rgb(138, 138, 138)'); Titlelabel.settext (' hangzhou warehouse '); titleLabel.setHTextPosition('left'); / / set the text in a horizontal direction relative to the location of the icon, the default value for the 'right' titleLabel setIconTextGap (10); / / set spacing between icon and text titleLabel setBorder (new ht. UI. Border. IndividualLineBorder (0, 0, 3, 0, 3162 e8 '#')) / / in the component drawing a straight line on the frame; Unlike LineBorder, this border can be drawn separately in one or more directions titlelabel.settextFont ('16px Arial '); header.addView(titleLabel, { height: 'match_parent', width: 'wrap_content', align: 'center' });Copy the code

Then the interaction part is made in the header. Js under SRC /controller by right clicking the menu bar and clicking the titleLabel position to appear the drop-down menu. The interaction of the event is controlled by controlling the mouse click event:

let title, contextMenu; export default function controller (view) { title = view.findViewById('title'); contextMenu = new ht.ui.ContextMenu(); / / right-click menu component contextMenu. SetLabelColor (' RGB (138, 138, 138)); contextMenu.setHoverRowBackground('#3664e4'); Contextmenu. setItems([{label: 'cN'}, {label: 'CN'}, {label: 'CN'}]); ContextMenu. AddViewListener ((e) = > {the if (e.k ind = = = 'action') {/ / HT custom event type title. The setText (e.i tem. Label); }}); Title.getview ().addeventListener (' mouseDown ', e => {if (contextmenu.isindom ()) {contextmenu.hide (); / / hide menu document. The removeEventListener (' mousedown, handleWindowClick); } else {var items = contextmenu.getitems (); for (var i = 0; i < items.length; i++) { items[i].width = title.getWidth(); } let windowInfo = ht. Default. GetWindowInfo (), / / get the current window left | top | width | titleRect = height parameter information title.getView().getBoundingClientRect(); contextMenu.show(windowInfo.left + titleRect.left, windowInfo.top + titleRect.top + titleRect.height); document.addEventListener('mousedown', handleWindowClick); }}); } function handleWindowClick(e) { if (! contextMenu.getView().contains(e.target) && ! Title.getview ().contains(e.target)) {// Check whether the element is in the array contextmenu.hide (); document.removeEventListener('mousedown', handleWindowClick); }}Copy the code
  • The bottom right side relative to the bottom right div contains a graph3dView that displays 3D in the center, a shelfPane that appears when you double click on a container or cargo, and a chart chartPane that appears in the bottom right. Add these three sections to the RelativeLayout layout container:

           

let relativeLayout = new ht.ui.RelativeLayout(); // Create a relativelayout.setid ('contentRelative'); relativeLayout.setBackground('#060811'); var htView = new ht.ui.HTView(graph3dView); htView.setId('contentHTView'); Relativelayout. addView(htView, {// Add 3d components to relativeLayout width: 'match_parent', height: 'match_parent'}); Relativelayout.addview (shelfPane, {// Add the details of the shelfPane component to the relativeLayout layout. Width: 220, height: 'wrap_content', align: 'right', marginRight: 30, marginTop: 30 }); Relativelayout. addView(chartPane, {// Add the chartPane component to the relativeLayout. Width: 220, height: 200, align: 'right', vAlign: 'bottom', marginRight: 30, marginBottom: 30 })Copy the code

Then add the right relativeLayout and the right header to the bottom right container splitLayout:

let splitLayout = new ht.ui.SplitLayout(); splitLayout.setSplitterVisible(false); splitLayout.setPositionType('absoluteFirst'); splitLayout.setOrientation('v'); SplitLayout. AddView (header, {region: 'first' / / specify the component area, optional value is: 'first' | 'second'}); splitLayout.addView(relativeLayout, { region: 'second' });Copy the code

Add the sidebar of the left part and all of the right part (i.e., splitLayout) to the entire bottom container, borderLayout, and add the bottom container to the HTML body:

let borderLayout = new BorderLayout(); borderLayout.setLeftWidth(250); BorderLayout. AddView (sidebar, {region: 'left', / / specify the component area, optional value is: 'top' | 'right' | 'bottom' | 'left' | 'center' width: 'match_parent'// component's preferred width}); borderLayout.addView(splitLayout, { region: 'center' }); borderLayout.addToDOM(); // Add the borderLayout to the bodyCopy the code

Let’s talk about the graph3dView, the 3D part contained within the relative layout, the shelfPane, which appears when you double click on a container or cargo, and the chartPane, which appears in the lower right corner of the diagram.

(1) graph3dView

The external interface to get the graph3dView from the index.js folder in SRC \ View \3d is called from the index.js folder in SRC/View:

import graph3dView from './3d/index';Copy the code

As you can see from this 3D scene, we need “floors”, “walls”, “shelves”, “forklifts”, “goods” and 3d scenes.

In index.js under the 3D folder, we import all the interfaces we need from the folder:

SceneWidth, sceneHeight, sceneTall, toShelfList, randomCargoType} from './ g.js '; Import {stockinout,// initiate inoutShelf} from './interfaces'; import { Shelf } from './shelf'; Import {Floor} from './ Floor '; Import {Wall} from './ Wall '; Import {Car} from './ Car '; Import {g3d} from './g3d'; Import {getCargoById} from './cargo'; / / the goodsCopy the code

The g3d.js file only sets the scene and listens for some events:

G3d.mi ((e) => {addInteractorListener const kind = e.type; If (kind === 'doubleClickData') {let data = e.data; If (data instanceof Shelf) {// If (data.settransparent (false); eventbus.fire({ type: 'cargoBlur' }); } else {data = data.a('cargo');} else {data = data.a('cargo'); if (! data) return; data.transparent = false; eventbus.fire({ type: 'cargoFocus', data: data }); } for (let i = shelfList.length - 1; i >= 0; Const shelf = shelfList[I]; shelf.setTransparent(true, data); } return; } if (kind === 'doubleClickBackground') {for (let I = shelflist.length - 1; i >= 0; Const shelf = shelfList[I]; shelf.setTransparent(false); } eventbus.fire({ type: 'cargoBlur' }); return; }});Copy the code

We define some base data in g.js that will be called repeatedly in any other referenced JS, so let’s parse this file first:

const sceneWidth = 1200; // Width const sceneHeight = 800; // Scene height const sceneTall = 410; // Depth of the scene const globalOpacity = 0.3; Const cargoTypes = {// carton' name': 'bucket'}, 'carton': {// carton' name': {// 'carton'} 'woodenBox1: {/ / wooden case 1' name ':' woodenBox1}, 'woodenBox2: {/ / wooden case 2' name ':' woodenBox2 '}};Copy the code

There are three functions, namely “obJ decomposition of shelves”, “loading model” and “type of randomly allocated goods” :

Function toShelfList(list) {const obj = {}; List.foreach ((o) => {view/3d/interface. Js const STRS = o.cubegeoid.split ('-'); let rs = obj[o.rackId]; if (! rs) { rs = obj[o.rackId] = []; } const ri = parseInt(strs[2].substr(1)) - 1; let ps = rs[ri]; if (! ps) { ps = rs[ri] = []; } let type = 'cask'; if (o.inventoryType === 'Import') { while((type = randomCargoType()) === 'cask') {} } const pi = parseInt(strs[3].substr(1)) - 1; ps[pi] = { id: o.cubeGeoId, type: type }; }); return obj; } function loadObj(shape3d, fileName, cbFunc) {const path = './objs/' + fileName; ht.Default.loadObj(path + '.obj', path + '.mtl', { shape3d: shape3d, center: true, cube: true, finishFunc: cbFunc }); } function randomCargoType() {const keys = object.keys (cargoTypes); const i = Math.floor(Math.random() * keys.length); return keys[i]; }Copy the code

There are also the indispensable “goods” and “shelves” as well as “forklifts” in this 3D scene. The three are defined in a similar way, and only “shelves” is explained here. We directly import the js file of the bottom “tray” into the JS file of the “goods” and treat them as a whole:

import { Pallet } from './pallet';
import {
  cargoTypes,
  loadObj,
  globalOpacity
} from './G';Copy the code

In the SRC \view\3d\cargo. Js file, we define a “cargo” class. This class declares a lot of methods. LoadObj: loadObj: loadObj: loadObj: loadObj: loadObj: loadObj: loadObj: loadObj: loadObj: loadObj: loadObj: loadObj: loadObj

For (let type in cargoTypes) {// Let type in cargoTypes array, const cargo = cargoTypes[type]; LoadObj (type, cargo. Name, (map, array, s3) => {//loadObj(shape3D, fileName, cbFunc) Parameters in cbFunc can be referencedObj manualcargo.s3 = s3; // Set cargo's s3 to the original size updateCargoSize(); }); } function updateCargoSize() { let c, obj; for (let i = cargoList.length - 1; i >= 0; i--) { c = cargoList[i]; obj = cargoTypes[c.type]; if (! obj.s3) continue; c.boxS3 = obj.s3; }}Copy the code

The main method is hT.default. startAnim function (HT for Web Animation Manual) encapsulated by HT. The outgoing animation is similar to the incoming animation, which will not be described here:

If (anim) {// If (anim) {// If (anim) {// If (anim) {// If (anim) {// If (anim) {// If (anim) {// If (anim) {// If (anim). } this.x = this.basicX + moveDistance; this.opacity = 1; Anim = ht.default. startAnim({duration: 1500, finishFunc: () => {// Call this function after the animation ends and set anim to null to stop animation anim = null; }, action: (v, t) => { this.x = this.basicX + (1 - v) * moveDistance; // Change the x coordinate to look like moving forward}}); }Copy the code

Ht. Node and HT. Shape are also very simple. We can simply inherit the hT. Node and HT. Shape properties.

Constructor (points, segments, tall, thickness, elevation) {super(); this.setPoints(points); // set "point" this.setSegments(segments); // Set the connection mode between dots this.settall (tall); // Controls the length of the Node element on the y axis this.setthickness (thickness); // Set the "thickness" this.setelevation (elevation); Opacity ': 0; // Opacity is 0.3 'all.reverse.flip': 0; // Opacity is 0.3 'all.reverse.flip': 0; // opacity is 0.3 'all.reverse.flip': 0 'bottom.visible': false// The bottom is not visible}); }}Copy the code

The four classes of Floor, Wall, shelf and CAR are ready. We just need to create a new object in SRC \view\3d\index.js and add it to the dataModel. Here we only show the initialization code of car “forklift” :

// init Car
const car = new Car();
car.addToDataModel(dm);Copy the code

As for “goods”, we use the timer to call in and out methods on this JS. Here is a simulated database interfaces.js file, if you need to look at it, we call it as data only.

SetInterval (() => {const obj = stockinout(); // let type = 'cask'; If (obj.inventoryType === 'Import') {while((type = randomCargoType()) === 'cask') {} car.cargoType = type; If (obj. InOutStatus = = = 'I') / / if the value is "I", are the car into the library. In (); Else // otherwise "o", car.out(); }, 30000);Copy the code

(2) shelfPane

The external interface to get graph3dView from shelfpane.js in SRC \ View \common is called by index.js in SRC/View:

import shelfPane from './common/shelfPane.js';Copy the code

ShelfPane is based on the Pane class. Introduce this class and event dispatcher in the shelfPane.js file:

import Pane from './Pane.js'; import eventbus from '.. /.. /controller/eventbus';Copy the code

The Pane class inherits from the HT.ui. TabLayout class wrapped in HT and makes some specific property Settings:

class Pane extends ht.ui.TabLayout { constructor() { super(); Enclosing setBorder (new ht. UI. Border. LineBorder (1, 'RGB (150150150))); / / set the component frame enclosing setTabHeaderBackground (null); / / set the tag line background, can be a color or pictures, etc. This setHoverTabBackground (null); / / set the Hover state under the label of the background, can be a color or pictures, etc. This setActiveTabBackground (null); This. setTitleColor(' RGB (184,184,184)'); This. setActiveTitleColor(' RGB (255,255,255)'); / / set the Active state of the color of the label text enclosing setTabHeaderLineSize (0); // Set the label line split width this.setmovable (false); / / set the label position can be adjusted drag and drop, the default is true. This setTabHeaderBackground (' # 1 c258c '); This. setTabGap(0); // Set the background of the label line, which can be a color or image. GetTabWidth (child) {const children = this.getChildren(), size = children.size(); if (size === 0) { return this.getContentWidth(); } else {return this.getContentWidth()/size; }} drawTab(g, child, x, y, w, h) const children = this.getChildren(), size = children.size(), Color = this. GetCurrentTitleColor (child), / / child components according to the parameters of state (normal, hover, active, move). Font = this.gettitleFont (child),// getTitleFont = this.getTitle(child); DrawText (g, title, font, color, x, y, w, h, 'left'); if (size === 1) {ht.default. drawText(g, title, font, color, x, y, w, h, 'left'); Else {ht.default. drawText(g, title, font, color, x, y, w, h, 'center'); } if (children.indexOf(child) < size - 1) { g.beginPath(); // start drawing g.point (x + w-1, y + 4, 1, h-8); G.f illStyle = 'RGB (150150150); g.fill(); } } show() { this.setVisible(true); } hide() {this.setVisible(false); }}Copy the code

The “information” list in our example is a table component. HT defines a table using hT.uI. TableLayout and then adds rows to the table using HT.ui. TableRow. In this example, “Remarks”, “Number”, “source”, “In”, “to”, and “out” are all text boxes. Take “Remarks” as an example:

let tableLayout = new ht.ui.TableLayout(); / / this layout to follow its own space ranks are divided into row. * the column cell tableLayout setColumnPreferredWidth (0, 45); / / set the column width tableLayout preferred. SetColumnWeight (0, 0). // Set the column width weight; If the layout of the total width is greater than the sum of the preferred width of all columns, then the rest of the width according to the weight distribution tableLayout. SetColumnPreferredWidth (1, 150); tableLayout.setPadding(8); // Set the inner margin of the component. If the parameter is a number, it means that the four sides use the same inner margin; Var tableRow1 = new ht.ui.tablerow (); var tableRow1 = new ht.ui.tablerow (); // A row of subcomponents in the table; var label = new ht.ui.Label(); // Label component label.settext (' remarks '); // Set the text content label.setalign ('left'); // Set the overall alignment of text and ICONS in the horizontal direction of the button. Default is 'center' label.settextColor (' RGB (255,255,255)'); Var textField = new ht.ui.textField (); / / text box component textField. SetFormDataName (' remark '); // Set the name of the component in the form textField.setBackground(null); // Set the background of the component. This value will be converted to the Drawable object textField. SetBorderRadius (0); Textfield. setColor(' RGB (138,138,138)'); // Set the text color textField.setPlaceholder(' none '); / / set the input prompt textField. SetBorder (new ht. UI. Border. IndividualLineBorder (0, 0, 1, 0, 'RGB (138138138))); // Set the component's border tablerow1.addView (label); // Add a child component tablerow1.addView (textField); tableLayout.addView(tableRow1); // Add the child component to the containerCopy the code

The ht.ui.ComboBox component encapsulated in HT is similar to hT.ui. TextField, but the specific operation is different. HT is easier to use and easier to use. Here we use “model” to parse. When setting up “pull down data” we use data binding in HT:

Var tableRow4 = new ht.ui.tablerow (); label = new ht.ui.Label(); Label the setText (' model '); label.setAlign('left'); Label. SetTextColor (' RGB (255255255)); var comboBox = new ht.ui.ComboBox(); comboBox.setFormDataName('model'); comboBox.setBackground(null); ComboBox. SetColor (' RGB (232143,49)); Combobobox. setDatas([//// sets drop down data array {label: 'carton', value: 'carton'}, {label: 'carton 1', value: 'woodenBox1'}, {label: '2' wooden box, value: 'woodenBox2'}, {label: 'buckets' value:' cask}]); comboBox.setIcon('imgs/combobox_icon.json'); comboBox.setHoverIcon('imgs/combobox_icon_hover.json'); comboBox.setActiveIcon('imgs/combobox_icon_hover.json'); comboBox.setBorderRadius(0); / / / / set the CSS border round comboBox. SetBorder (new ht. UI. Border. IndividualLineBorder (0, 0, 1, 0, 'RGB (138138138))); tableRow4.addView(label); tableRow4.addView(comboBox); tableLayout.addView(tableRow4);Copy the code

ColorPicker component, which inherits from ht.ui.bobox and uses HT.ui.colorDropdown as a drop-down template, similar to the previous drop-down list, except that the drop-down template has been changed:

Var tableRow9 = new ht.ui.tablerow (); label = new ht.ui.Label(); Label the setText (' stain '); label.setAlign('left'); Label. SetTextColor (' RGB (255255255)); var comboBox = new ht.ui.ColorPicker(); // Combobobox. SetFormDataName ('blend'); // Set the name of the component in the form combobox.getView ().className = 'content_colorpicker'; comboBox.setBackground(null); comboBox.setPreviewBackground(null); // Set the preview background; Combobobox.getinput ().style. Visibility = 'visible'; ComboBox. SetReadOnly (true); // set combobox.setcolor ('rgba(0,0,0,0)'); Combobobox. SetPlaceholder (' Change container color '); comboBox.setIcon('imgs/combobox_icon.json'); comboBox.setHoverIcon('imgs/combobox_icon_hover.json'); comboBox.setActiveIcon('imgs/combobox_icon_hover.json'); comboBox.setBorderRadius(0); ComboBox. SetBorder (new ht. UI. Border. IndividualLineBorder (0, 0, 1, 0, 'RGB (138138138))); comboBox.setInstant(true); // Set instant mode; In this mode, the tablerow9.addView (label) event is dispatched immediately every time a character of value is entered, otherwise it is dispatched only when you lose focus or hit enter. tableRow9.addView(comboBox); tableLayout.addView(tableRow9);Copy the code

Finally, the addChangeListener event listener function of hT.ui. Form component is used to monitor the overall change event of JSON and the change event of a single piece of data in JSON. The two events are explained as follows:

Specific monitoring methods are as follows:

form.addChangeListener((e) => { const cargo = form.__cargo__; If (e.type === 'formDataValueChange') {//JSON const name = e.name; let value = e.newValue; if (name === 'blend') { if (value && value.startsWith('rgba')) { const li = value.lastIndexOf(','); value = 'rgb' + value.substring(value.indexOf('('), li) + ')'; } } cargo.setValue(name, value); }});Copy the code

The HT. Notifier event dispatcher (HT. Notifier) enables components in different areas on the INTERFACE to interact with each other through event dispatcher and performs different actions according to different event types.

Eventbus. add((e) => {// add listener eventbus; Components in different areas of the interface interact with each other via event distribution if (e.type === 'cargoFocus') {shelfpane.show (); const cargo = e.data; form.__cargo__ = cargo; const json = form.getJSON(); For (let k in JSON) {form.setitem (k, cargo. GetValue (k)); } return; } if (e.type === 'cargoBlur') { shelfPane.hide(); return; }});Copy the code

(3) chartPane

import chartPane from './common/chartPane.js';Copy the code

ChartPane and shelfPane are similar in that they are objects of the Pane class and have similar properties, except content. Because today’s Demo is only a Demo, we haven’t done much about chart plugins, so we use pictures instead of dynamic charts, but even if we want to do it, it is very easy to do, HT third-party plugins are also very easy to use, you can see the example here hightopo.com/demo/large-… There are more interesting examples on the HT website!

Getting back to business, the chartPane chart panel is easy to implement by adding background images of internal child components to the chartPane Chart panel:

import Pane from './Pane.js'; var chartPane = new Pane(); var view1 = new ht.ui.View(); view1.setBackgroundDrawable(new ht.ui.drawable.ImageDrawable('imgs/chart.png', 'fill')); // Set the component's background Drawable object; Var view2 = new ht.ui.view (); view2.setBackgroundDrawable(new ht.ui.drawable.ImageDrawable('imgs/chart.png', 'fill')); ChartPane. GetView (). Style. Background = 'rgba (18,28,64,0.60); // Set the background color chartpane.addView (view1, {// add the child component to the container title: 'Other charts'}); Chartpane.addview (view2, {title: 'Inventory load'}); chartPane.setActiveView(view2); // Sets the selected child componentCopy the code

After the analysis of the whole example, interested partners can go to the OFFICIAL WEBSITE of HT for self-study and reference. Have a good taste and you will find a bigger world.