基于 HTML5 WebGL 的 3D 仓储管理系统

仓储管理系统(WMS)是一个实时的计算机软件系统,它能够按照运作的业务规则和运算法则,对信息、资源、行为、存货和分销运作进行更完美地管理,使其最大化满足有效产出和精确性的要求。从财务软件、进销存软件CIMS,从MRP、MRPII到ERP,代表了中国企业从粗放型管理走向集约管理的要求,竞争的激烈和对成本的要求使得管理对象表现为:整和上游、企业本身、下游一体化供应链的信息和资源。而仓库,尤其是制造业中的仓库,作为链上的节点,不同链节上的库存观不同,在物流供应链的管理中,不再把库存作为维持生产和销售的措施,而将其作为一种供应链的平衡机制,其作用主要是协调整个供应链。但现代企业同时又面临着许多不确定因素,无论他们来自分供方还是来自生产或客户,对企业来说处理好库存管理与不确定性关系的唯一办法是加强企业之间信息的交流和共享,增加库存决策信息的透明性、可靠性和实时性。而这,正是WMS所要帮助企业解决的问题。

WMS软件和进销存管理软件的最大区别在于:进销存软件的目标是针对于特定对象(如仓库)的商品、单据流动,是对于仓库作业结果的记录、核对和管理——报警、报表、结果分析,比如记录商品出入库的时间、经手人等;而WMS软件则除了管理仓库作业的结果记录、核对和管理外最大的功能是对仓库作业过程的指导和规范:即不但对结果进行处理,更是通过对作业动作的指导和规范保证作业的准确性、速度和相关记录数据的自动登记(入计算机系统),增加仓库的效率、管理透明度、真实度降低成本比如通过无线终端指导操作员给某定单发货:当操作员提出发货请求时,终端提示操作员应到哪个具体的仓库货位取出指定数量的那几种商品,扫描货架和商品条码核对是否正确,然后送到接货区,录入运输单位信息,完成出货任务,重要的是包括出货时间、操作员、货物种类、数量、产品序列号、承运单位等信息在货物装车的同时已经通过无线方式传输到了计算机信息中心数据库。
由于市场需求量较大,我们来好好解析今天这个例子。
动图如下:
可以在  http://download.csdn.net/download/u013161495/10136727 下载代码。具体运行代码请参考readme.html。
这个例子是采用 es6 的模块化的方式部署的。打开 index.html 进入 lib/index.js,源码是在 src 文件夹中,我们直接进 src/view 下的 index.js 
 在顶部加载其他模块中含有 export 接口的模块:
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';

我们将页面上的每个部分分开来放在不同的 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 两个方法:
let BorderLayout = function() {
    BorderLayout.superClass.constructor.call(this);
    this.setContinuous(true);
    this.setSplitterSize(0);
};

ht.Default.def(BorderLayout, ht.ui.BorderLayout, {
    //自定义类
    /**
     * splitter 宽度都为 0,为了能正常交互,重写此函数将 splitterRect 的宽度修改为 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);
    },
    /**
     * 调整左侧 splitterCanvas 的尺寸,以便挡住子组件
     * @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;
  • 左侧栏 sidebar,分为 8 个部分:顶部 logo、货位统计表格、进度条、分割线、货物表格、图表、管理组、问题反馈按钮等。

           

可以查看 src/view 下的 sidebar.js 文件,这个 js 文件中同样加载了  src/view/common 下的TreeHoverBackgroundDrawable.js 和 ProgressBarSelectBarDrawable.js 中的  TreeHoverBackgroundDrawable 和 ProgressBarSelectBarDrawable 变量,以及 src/controller 下的 sidebar.js 中的 controller 变量:

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

HT 封装了一个 ht.ui.VBoxLayout 函数,用来将子组件放置在同一垂直列中,我们可以将左侧栏要显示的部分都放到这个组件中,这样所有的部分都是以垂直列排布:

let vBoxLayout = new ht.ui.VBoxLayout();//此布局器将子组件放置在同一垂直列中;
vBoxLayout.setBackground('#17191a');

顶部 logo 是根据在 Label 标签上添加 icon 的方法来实现的,并将这个 topLabel 添加进垂直列 vBoxLayout 中:

let topLabel = new ht.ui.Label(); //标签组件
topLabel.setText('Demo-logo');//设置文字内容
topLabel.setIcon('imgs/logo.json');//设置图标,可以是颜色或者图片等
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, {
    //将子组件加到容器中
    width: 'match_parent'//填满父容器 
});

对于“货位统计表格”,我们采用的是 HT 封装的 TreeTableView 组件,以树和表格的组合方式呈现 DataModel 中数据元素属性及父子关系,并将这个“树表”添加进垂直列 vBoxLayout 中:

let shelfTreeTable = new ht.ui.TreeTableView();//树表组件,以树和表格的组合方式呈现 DataModel 中数据元素属性及父子关系
shelfTreeTable.setHoverBackgroundDrawable(new TreeHoverBackgroundDrawable('#1ceddf', 2));//设置 hover 状态下行选中背景的 Drawable 对象
shelfTreeTable.setSelectBackgroundDrawable(new TreeHoverBackgroundDrawable('#1ceddf', 2));//设置行选中背景的 Drawable 对象 参数为“背景
shelfTreeTable.setBackground(null);
shelfTreeTable.setIndent(20);//设置不同层次的缩进值
shelfTreeTable.setColumnLineVisible(false);//设置列线是否可见
shelfTreeTable.setRowLineVisible(false);
shelfTreeTable.setExpandIcon('imgs/expand.json');//设置展开图标图标,可以是颜色或者图片等
shelfTreeTable.setCollapseIcon('imgs/collapse.json');//设置合并图标图标,可以是颜色或者图片等
shelfTreeTable.setPreferredSizeRowCountLimit();//设置计算 preferredSize 时要限制的数据行数
shelfTreeTable.setId('shelfTreeTable');
vBoxLayout.addView(shelfTreeTable, {
    width: 'match_parent',
    height: 'wrap_content',//组件自身首选高度
    marginTop: 24,
    marginLeft: 4, 
    marginRight: 4
});

我们在设置“行选中”时背景传入了一个 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 中新添加的属性:

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 = 
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吃货乙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值