• BOM树的构造


     

     

    物料清单是是描述企业产品组成的技术文件。在加工资本式行业,它表明了产品的总装件、分装件、组件、部件、零件、直到原材料之间的结构关系,以及所需的数量。在化工、制药和食品行业产品组成则对主要原料、中间体、辅助材料及其配方和所需数量的说明。BOM是将用图表示的产品组成改用数据表格的形式表示出来,它是MRPII系统中计算MRP过程中的重要控制文件。

        ERP系统需求。本次版本的所有功能需求都是建立在老版本ERP之上的,所以本文档的功能需求以及业务逻辑完全COPY原来版本,而修改的是实现方式。

    树的设计

    首先,新建一个物料清单(以下简称BOM)的时候,我们设计的页面是左边的树结构没有数据,而在一张BOM单据保存建立之后,相应的页面左边的树结构将会把本BOM所对应的BOM母件和子件以及子件的BOM信息数据加载过来,并且在页面的左下部其BOM单据的母件图片也会显示出来(如图示12)。

     

    图示1BOM新建时的页面显示状态)

     

    图示2BOM保存后生成单据后页面树结构显示状态)

     

       另外,我们要在这里分析以下这个数的数据结构。首先从图示2中可以看到BOM树的根节点的文本是母件的品名和BOM版本号拼接起来的一个文本字符串,而子节点的文本是当前BOM下的所有子件品名信息,但是其中的子件文本信息还是有条件的显示的。如果这个子件单纯的是个子件的话,那就把子件品名信息文本显示出来就行了,且没有下级结点;而当该子件本身是一个BOM的是时候我们要分两种情况来判断他在当前BOM的显示状态,即:如果该子件的BOM有多个版本(两个或两个以上版本)的话,子件的显示状态是显示子件品名文本且该子节点有下级结点,那么这个子件的下级结点应该是该子件所有不同版本BOM的信息(该子件BOM信息也是由子件名称和相应的版本号拼接起来的);而如果该子件BOM只有一个版本的话呢,我们只需要把该子件BOM信息(由子件名称和相应的版本号拼接起来的文本)替代该子件的品名来显示(图示2就是这种情况)。

    树的代码实现

    首先,在ASPX页面上要用到EXT中的TreePanel控件,这个控件的属性以及相关事件的代码截图如:

    图示2

    从上面的截图看到,这棵树的根节点是一个异步树节点,而且在这个树控件上次根节点默认为不显示的;另外,在这棵树中好定义了一个BeforeLoad监听事件,这个事件的作用是加载当前树节点中其子节点的数据,而且吧这些数据装载到这棵树中。具体代码如下:

    function nodeLoad(node) {//参数node是当前展开的节点对象

        var billid = document.getElementById('txtIdentityID').value;//BOM单据的BillID

        if (billid > 0) {

            var splitIndex = node.id.indexOf("_");//请注意树节点的数据结构:

            if (splitIndex == -1) {

    //发送一次请求到服务器端进行数据处理

                Ext.net.DirectMethods.NodeLoad(billid, node.id, {

                    success: function(result) {

                        var data = eval("(" + result + ")");

                        node.loadNodes(data);

                    },

                    failure: function(errorMsg) {

                        Ext.Msg.alert('Failure', errorMsg);

                    }

                });

            }

            else {

                var splitstr = node.id.split("_");

                if (splitstr[0] == "1") {

    //发送一次请求到服务器端进行数据处理

                    Ext.net.DirectMethods.AddSubModules(splitstr[1], {

                        success: function(result) {

                            var data = eval("(" + result + ")");

                            node.loadNodes(data);

                        },

                        failure: function(errorMsg) {

                            Ext.Msg.alert('Failure', errorMsg);

                        }

                    });

                }

                if (splitstr[0] == '11') {

    //发送一次请求到服务器端进行数据处理

                    Ext.net.DirectMethods.NodeLoad(splitstr[1], splitstr[1], {

                        success: function(result) {

                            var data = eval("(" + result + ")");

                            node.loadNodes(data);

                        },

                        failure: function(errorMsg) {

                            Ext.Msg.alert('Failure', errorMsg);

                        }

                    });

                }

            }

        }

    }

    可以看到在这个方法中,有几次条件判断以及在不同条件下执行了不同的请求;这些条件是通过树节点的nodeId来建立的,nodeId的数据结构是这样子的:DOM根节点(DOM母件节点)的nodeID是此BOM单据的ID,而其子节点的nodeID是有多个字符串拼接起来的,具体可以看一下下面的服务器端代码(注意红色标记部分):

        #region 绑定Bom清单

        [DirectMethod]

        public string NodeLoad(int BomID, int nodeID)

        {

            string companyCD = ((UserInfoUtil)SessionUtil.Session["UserInfo"]).CompanyCD;

            BomModel model = new BomModel();

            model.CompanyCD = companyCD;

            model.ID = BomID;

            DataTable dt = BomBus.GetBomsInfoByID(model);

            Ext.Net.TreeNodeCollection nodes = new Ext.Net.TreeNodeCollection();

            if (dt.Rows.Count > 0)

            {

                string Bom_Nodeid = dt.Rows[0]["ID"].ToString();

                string strDateTime = DateTime.Now.ToString("yyyyMMddhhmmss");

                if (nodeID == 0)

                {

                    Ext.Net.AsyncTreeNode asyncNode = new AsyncTreeNode();

                    if (!string.IsNullOrEmpty(dt.Rows[0]["Verson"].ToString()))

                    {

                        asyncNode.Text = dt.Rows[0]["ProductName"].ToString() + "(" + dt.Rows[0]["Verson"].ToString() + ")";

                    }

                    else

                    {

                        asyncNode.Text = dt.Rows[0]["ProductName"].ToString();

                    }

                    asyncNode.NodeID = dt.Rows[0]["ID"].ToString();//BOM根节点的NODEID

                    asyncNode.Listeners.Click.Handler = "LoadBomInfo(" + asyncNode.NodeID.ToString() + ",'checktree')";

                    nodes.Add(asyncNode);

                }

                else

                {

                    foreach (DataRow row in dt.Select("ID='0'"))

                    {

                        Ext.Net.AsyncTreeNode asyncSubNode = new AsyncTreeNode();

                        if (row["IsBasicBom"].ToString() == "0")

                        {

                            asyncSubNode.Text = row["ProductName"].ToString();

                            asyncSubNode.NodeID = "0_" + row["ProductID"].ToString() + "_" + Bom_Nodeid + "_" + strDateTime;//一个子节点的NODEID

                            asyncSubNode.Leaf = true;

                            asyncSubNode.Listeners.Click.Handler = "LoadBomInfo(" + Bom_Nodeid.ToString() + ",'checktree')";

                        }

                        else

                        {

                            BomModel model1 = new BomModel();

                            model1.CompanyCD = companyCD;

                            model1.ProductID = row["ProductID"].ToString();

     

                            DataTable dt1 = BomBus.GetBomsByProductID(model1);

                            if (dt1.Rows.Count == 1)

                            {

                                if (!string.IsNullOrEmpty(dt1.Rows[0]["Verson"].ToString()))

                                {

                                    asyncSubNode.Text = dt1.Rows[0]["ProductName"].ToString() + "(" + dt1.Rows[0]["Verson"].ToString() + ")";

                                }

                                else

                                {

                                    asyncSubNode.Text = dt1.Rows[0]["ProductName"].ToString();

                                }

                                asyncSubNode.NodeID = "11_" + dt1.Rows[0]["ID"].ToString() + "_" + strDateTime;//子节点的NODEID

                                asyncSubNode.Listeners.Click.Handler = "LoadBomInfo(" + dt1.Rows[0]["ID"].ToString() + ",'checktree')";

                            }

                            else

                            {

                                asyncSubNode.Text = row["ProductName"].ToString();

                                asyncSubNode.NodeID = "1_" + row["ProductID"].ToString() + "_" + Bom_Nodeid + "_" + strDateTime;子节点的NODEID

     

                                asyncSubNode.Listeners.Click.Handler = "LoadBomInfo(" + Bom_Nodeid.ToString() + ",'checktree')";

                            }

                        }

                        nodes.Add(asyncSubNode);

                    }

                }

            }

            return nodes.ToJson();

        }

        //递归

        [DirectMethod]

        public string AddSubModules(string productid)

        {

            string companyCD = ((UserInfoUtil)SessionUtil.Session["UserInfo"]).CompanyCD;

            Ext.Net.TreeNodeCollection nodes = new Ext.Net.TreeNodeCollection();

            string strDateTime = DateTime.Now.ToString("yyyyMMddhhmmss");

     

            BomModel model = new BomModel();

            model.CompanyCD = companyCD;

            model.ProductID = productid;

     

            DataTable dt = BomBus.GetBomsByProductID(model);

            //DataRow[] rows = userModules.Select("SuperDeptID = '" + moduleId + "'");

            foreach (DataRow row in dt.Rows)

            {

                Ext.Net.AsyncTreeNode asyncNode = new Ext.Net.AsyncTreeNode();

                if (!string.IsNullOrEmpty(row["Verson"].ToString()))

                {

                    asyncNode.Text = row["ProductName"].ToString() + "(" + row["Verson"].ToString() + ")";

                }

                else

                {

                    asyncNode.Text = row["ProductName"].ToString();

                }

                asyncNode.NodeID = "11_" + row["ID"].ToString() + "_" + strDateTime;

                asyncNode.Listeners.Click.Handler = "LoadBomInfo(" + row["ID"].ToString() + ",'checktree')";

                nodes.Add(asyncNode);

            }

            return nodes.ToJson();

        }

        #endregion

    这些红色字体标记部分就是通过“标记_子件物品ID或子件BOMID_当前时间”的格式拼接起来的,这样的拼接可以保证个节点的NODEID是不一样的,并且“标记”元素的设计可以在JS的方法nodeLoad()中作为很好的判断条件,这个标记是这样设计的:当子件不是BOM时,标记=0;当子件只有一个版本BOM时,标记=11 而当子件有多个版本的BOM时,标记=1

        我们接着看上面这段代码。这段代码是获取DOM树中数据的一个方法,是和JS中的方法nodeLoad()相关联的,且看上面两段代码(jscs两部分代码)中标记为绿色字体部分,这部分代码是关联在一起的,首先在一定条件下JS端(浏览器端)可以分别通过一个请求直接调用了CS代码中的NodeLoad(int BomID, int nodeID)方法或者string AddSubModules(string productid)方法,这两个CS中的代码使用递归的方式来获取所需数据,之后返回到JS端(浏览器端)使其接收到数据后,使用node.loadNodes(data);来给树添加数据。

     

    至此,整个BOM树的数据处理过程基本已经结束。其中的关键是对这棵树结构的理解。

     

  • 相关阅读:
    设计模式のIteratorPattern(迭代器模式)----行为模式
    设计模式のChainOfResponsibilityPattern(责任链模式)----行为模式
    设计模式のProxyPattern(代理模式)----结构模式
    设计模式のFlyweight(享元模式)----结构模式
    设计模式のFacadePattern(外观模式)----结构模式
    js代码判断浏览器种类IE、FF、Opera、Safari、chrome及版本
    实现图片预加载
    移动端 下滑时加载新数据
    各种高度
    js验证input输入正整数 和 输入的金额小数点后保留两位(PC端键盘输入)
  • 原文地址:https://www.cnblogs.com/xinzeda/p/2161903.html
Copyright © 2020-2023  润新知