bifa365必发Winform开发框架的客户关系管理体系(CRM)的支付总结系列3-客户分类与布局管理落实

自以随系列随笔的上马,介绍了CRM系统一个根本之客户分类的示界面,其中蕴含了起字典中加载分类、从曾经生数量被加载分类、以及分组列表中加载分类等艺术的贯彻,以及可以动态对这些节点开展配置,实现客户分类的界面配置处理。本文主要由逻辑代码实现之角度达解释以上功能的落实,介绍健康字典模块的动态加载、客户省都之动态加载、客户分组管理、客户分类布局管理等于模块的切实可行落实。

貌似情形下,我们对客户的分类且要动态加载,对斯客户分类的管理,包括下面几乎种分类。

1、常规字典模块的动态加载

bifa365必发 1  bifa365必发 2

如上节点是于字典模块的数量里面进行动态加载的,根据节点的两样,显示的情见仁见智。

率先我们要以数据库中建立一个说明,用来记录得出示的异常之归类节点,如客户状态、客户类型、客户级别这些层次之节点,如下所示。

bifa365必发 3

根据此表底始末指引,我们以动态加载中的子节点。

            TreeNode topNode = new TreeNode("全部客户", 0, 0);
            this.treeView1.Nodes.Add(topNode);

            List<SystemTreeNodeInfo> propList = BLLFactory<SystemTree>.Instance.GetTree("客户属性分类");
            foreach (SystemTreeNodeInfo nodeInfo in propList)
            {
                if (ContainTree(nodeInfo.ID))
                {
                    TreeNode subNode = new TreeNode(nodeInfo.TreeName, 1, 1);
                    AddSystemTree(nodeInfo.Children, subNode, 2);
                    this.treeView1.Nodes.Add(subNode);
                }
            }
            this.treeView1.ExpandAll();

            for (int i = 0; i < this.treeView1.Nodes.Count; i++)
            {
                TreeNode node = this.treeView1.Nodes[i];
                AddDictData(node, 3);
            }

 其中以递归函数进行创办树节点,也便是养节点可以是多层级的。

        /// <summary>
        /// 从系统树形表里面获取数据,绑定客户属性分类和客户状态分类
        /// </summary>
        private void AddSystemTree(List<SystemTreeNodeInfo> nodeList, TreeNode treeNode, int i)
        {
            foreach (SystemTreeNodeInfo nodeInfo in nodeList)
            {
                if (ContainTree(nodeInfo.ID))
                {
                    TreeNode subNode = new TreeNode(nodeInfo.TreeName, i, i);
                    subNode.Tag = nodeInfo.SpecialTag;//用来做一定的标识
                    treeNode.Nodes.Add(subNode);

                    AddSystemTree(nodeInfo.Children, subNode, i + 1);
                }
            }
        }

面代码首先由一个SystemTree的业务对象中加载列表信息,然后经一个递归函数AddSystemTree兑现节点的加载。

加载大之树节点完毕后,我们虽由字典中落相应的字典项目性质进行加载了,我们随便上面的树节点是拼,我们惟有待掌握,上面每一个节点都从数据库获取相应的花色进展绑定即可,从字典加载子节点的代码逻辑如下所示。

                List<DictDataInfo> dict = BLLFactory<DictData>.Instance.FindByDictType(treeNode.Text);
                foreach (DictDataInfo info in dict)
                {
                    if (ContainTree(info.ID))
                    {
                        TreeNode subNode = new TreeNode(info.Name, i, i);
                        if (treeNode.Tag != null)
                        {
                            subNode.Tag = string.Format("{0}='{1}' ", treeNode.Tag, info.Value);
                        }
                        treeNode.Nodes.Add(subNode);
                    }
                }

2、客户省、客户都会之动态加载

除由数据字典中加载的节点数据,还有同栽要客户省、客户都会,我们了解这些多少十分特别,我们只要以树列表中展示全国的都会,那么一定是坏的用户体验,想想要当举国上下几百独都寻找一个下可免易于。

于是乎,可以设计于曾出客户所在的省、所在的都会,把她们动态加载出来,数据就是丢掉那个多,友好很多,界面效果图如下所示。

bifa365必发 4 
 bifa365必发 5

刚我们看出了,从数字典中动态加载子节点的操作了,其实是和地方的操作看似,只是获取数据源的地方不同而已,我们可根据树的节点(特殊节点)来针对数据源进行不同的加载,具体如下代码所示。

        /// <summary>
        /// 从数据库获取对应字典数据,并绑定到相关节点上
        /// </summary>
        private void AddDictData(TreeNode treeNode, int i)
        {
            string nodeText = treeNode.Text;
            if (nodeText == "客户省份")
            {
                List<string> provinceList = BLLFactory<Customer>.Instance.GetCustomersProvince();
                foreach (string province in provinceList)
                {
                    TreeNode subNode = new TreeNode(province, i, i);
                    if (treeNode.Tag != null)
                    {
                        subNode.Tag = string.Format("{0}='{1}' ", treeNode.Tag, province);
                    }
                    treeNode.Nodes.Add(subNode);
                }
            }
            else if (nodeText == "客户城市")
            {
                List<string> cityList = BLLFactory<Customer>.Instance.GetCustomersCity();
                foreach (string city in cityList)
                {
                    TreeNode subNode = new TreeNode(city, i, i);
                    if (treeNode.Tag != null)
                    {
                        subNode.Tag = string.Format("{0}='{1}' ", treeNode.Tag, city);
                    }
                    treeNode.Nodes.Add(subNode);
                }
            }

透过事先在节点内定义有性,我们虽可知构建一个方可查询有对数据的过滤语句了,然后于培训之AfterSelect事件中实现对极语句的询问即可。

        string treeConditionSql = "";
        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (e.Node != null)
            {
                //需要清空查询输入条件
                this.customGridLookUpEdit1.EditValue = null;

                if (e.Node.Tag != null && !string.IsNullOrEmpty(e.Node.Tag.ToString()))
                {
                    treeConditionSql = e.Node.Tag.ToString();
                    BindData();
                }
.....................

陶铸之动态加载在众地方都可以为此到,例如下面的界面中,我本着订单的各种性能状态进行了分类,方便操作。

bifa365必发 6

3、客户分组的管住

除外上面两种,还有雷同种来自个人的客户组别的数据表数据,我们于内获得到相应的客户分组信息,然后于客户分组节点受到显下,选择相应的私有分组就可以获取相应之客户。

bifa365必发 7

方的个体分组来自对客户的民用分组表里面,它的管制界面如下所示。

bifa365必发 8

个人分组的子节点加载操作代码如下所示,其中除加载已部分客户分组外,还加有限单分组名称,如“未分组客户”和“全部客户”,方便操作。

            TreeNode myGroupNode = new TreeNode("个人分组", 4, 4);
            List<CustomerGroupNodeInfo> groupList = BLLFactory<CustomerGroup>.Instance.GetTree(LoginUserInfo.Name);
            AddCustomerGroupTree(groupList, myGroupNode, 3);
            //添加一个未分类和全部客户的组别
            myGroupNode.Nodes.Add(new TreeNode("未分组客户", 3, 3));
            myGroupNode.Nodes.Add(new TreeNode("全部客户", 3, 3));

            this.treeView1.Nodes.Add(myGroupNode);
            myGroupNode.ExpandAll();

        /// <summary>
        /// 获取客户分组并绑定
        /// </summary>
        private void AddCustomerGroupTree(List<CustomerGroupNodeInfo> nodeList, TreeNode treeNode, int i)
        {
            foreach (CustomerGroupNodeInfo nodeInfo in nodeList)
            {
                if (ContainTree(nodeInfo.ID))
                {
                    TreeNode subNode = new TreeNode(nodeInfo.Name, i, i);
                    treeNode.Nodes.Add(subNode);

                    AddCustomerGroupTree(nodeInfo.Children, subNode, i);
                }
            }
        }

接下来以AfterSelect事件受到拍卖即可实现对应数据的询问操作了。

                    else if (e.Node.FullPath.IndexOf("个人分组") >= 0)
                    {
                        if (e.Node.Text == "全部客户")
                        {
                            treeConditionSql = "";
                            BindData();
                        }
                        else if (e.Node.Text == "未分组客户")
                        {
                            isUserGroupName = true;
                            BindDataWithGroup(null);
                        }
                        else
                        {
                            isUserGroupName = true;
                            BindDataWithGroup(e.Node.Text);
                        }
                    }

        private void BindDataWithGroup(string groupName)
        {
            //entity
            this.winGridViewPager1.DisplayColumns = displayColumns;
            this.winGridViewPager1.ColumnNameAlias = BLLFactory<Customer>.Instance.GetColumnNameAlias();//字段列显示名称转义

            List<CustomerInfo> list = BLLFactory<Customer>.Instance.FindByGroupName(LoginUserInfo.Name, groupName, this.winGridViewPager1.PagerInfo);
            this.winGridViewPager1.DataSource = new WHC.Pager.WinControl.SortableBindingList<CustomerInfo>(list);
            this.winGridViewPager1.PrintTitle = "客户信息列表";
        }

地方的代码中因故到了目前用户的登陆名称作为一个标识(LoginUserInfo.Name),用来就获得当前用户的分组信息之。

4、客户分类的安排管理

从今上面对客户之归类,我们看到曾经发出无数特别的门类了,每个品种进行还有某些项,这样即使结成了一个分外怪之树,但是有时小客户或未肯定对所有的归类节点都感谢兴趣,如果能吃客户一个摘取安排的时,会显愈发自己

bifa365必发 9 

 上面我们提供了一个单身的界面元素配置窗口于用户展开打定义之树节点配置,我们约定默认(在用户还从未保留配置的时光)是管持有节点勾选上去,如果用户选定并保留了,那么为用户配置的吗依照来加以载树列表。

下我们来看望现实怎么着兑现这操作的。

第一我们当用户初始化树的时光,把用户之保留列表获取到,并保存在一个有的变量里面,方便对节点开展判定,如下代码所示。

        private void InitTree()
        {
            userTreeList = BLLFactory<UserTreeSetting>.Instance.GetTreeSetting(treeCategory, LoginUserInfo.ID.ToString());

然后我们编辑一个函数,用来判定是否要勾选上去。刚才说交,默认如果无保存,则需勾选上去。

        /// <summary>
        /// 如果列表为空或包含指定ID,则认为包含
        /// </summary>
        /// <param name="id">树ID节点</param>
        /// <returns></returns>
        private bool ContainTree(string id)
        {
            bool result = false;
            if (userTreeList == null || userTreeList.Count == 0 || userTreeList.Contains(id))
            {
                result = true;
            }
            return result;
        }

然后我们添加每个树节点的下,使用这个函数判断是否勾选上去即可,注意每个节点的Tag使用了一个GUID作为记录,方便保存。

            List<SystemTreeNodeInfo> propList = BLLFactory<SystemTree>.Instance.GetTree("客户属性分类");
            foreach (SystemTreeNodeInfo nodeInfo in propList)
            {
                TreeNode subNode = new TreeNode(nodeInfo.TreeName, 1, 1);
                subNode.Tag = nodeInfo.ID;
                subNode.Checked = ContainTree(nodeInfo.ID);

                AddSystemTree(nodeInfo.Children, subNode, 2);
                this.treeView1.Nodes.Add(subNode);
            }
            this.treeView1.ExpandAll();

末了,保存节点的早晚,我们遍历每个节点的Tag的GUID内容,然后将它们保存至用户配置表里面即可。

        private void btnOK_Click(object sender, EventArgs e)
        {
            List<string> nodeIdList = new List<string>();
            foreach (TreeNode node in this.treeView1.Nodes)
            {
                if (node.Checked && node.Tag != null && !string.IsNullOrEmpty(node.Tag.ToString()))
                {
                    nodeIdList.Add(node.Tag.ToString());
                }
                nodeIdList.AddRange(GetNodeIdList(node));
            }

            bool result = BLLFactory<UserTreeSetting>.Instance.SaveTreeSetting(treeCategory, LoginUserInfo.ID.ToString(), nodeIdList);
            if (result)
            {
                ProcessDataSaved(null, null);
                MessageDxUtil.ShowTips("保存成功");
            }            
            this.Close();
        }

通过以上这些操作,我们就算会当布置界面被,显示用户之选项节点,然后可以保存用户的挑选内容及一个独门的配置表里面,在标准的树列表中,我们之所以同样的方来判断用户是否勾选了相应的节点,如果没勾选,那么我们不用创建是节点即可,如下面的代码所示。

            List<SystemTreeNodeInfo> propList = BLLFactory<SystemTree>.Instance.GetTree("客户属性分类");
            foreach (SystemTreeNodeInfo nodeInfo in propList)
            {
                if (ContainTree(nodeInfo.ID))
                {
                    TreeNode subNode = new TreeNode(nodeInfo.TreeName, 1, 1);
                    AddSystemTree(nodeInfo.Children, subNode, 2);
                    this.treeView1.Nodes.Add(subNode);
                }
            }

如上就是本身之CRM系统模块里面的一些常用界面元素具体实现逻辑,希望对大家解析上有帮助。

本CRM系统重要性是因自己的《Winform开发框架》基础及拓展的模块出,其中成了全副框架体系里的权能管理模块、字典管理模块、Winform分页控件、公用类库、自动更新模块、附件管理模块、人员管理模块,以及持续可能用做的流程管理模块、邮件收发服务模块、信息通知模块等同样系列内容,希望开出一个高效、易用的客户保管体系,同时也盼望吃此系统的支付实践,进一步改良自身之代码生成工具,以及更健全Winform开发框架各模块的始末,达到新的一个冲天。

《Winform开发框架》的首要成效概览如下图所示。

bifa365必发 10

自之欠CRM系统系列的几乎首随笔链接如下,供阅读。

Winform开发框架的客户关系管理网bifa365必发(CRM)的开支总结系列1-界面功能展示 

Winform开发框架的客户关系管理网(CRM)的开总结系列2-基于框架的支付进程 

Winform开发框架的客户关系管理网(CRM)的开发总结系列3-客户分类和部署管理落实 

Winform开发框架的客户关系管理体系(CRM)的开总结系列4-Tab控件页面的动态加载 

发表评论

电子邮件地址不会被公开。 必填项已用*标注