话术脚本开发

  1.各层的作用?

    数据访问层(DAL层):主要是对原始数据(数据库或者文本文件等存放数据的形式)的操作层,是对数据的操作,具体为业务逻辑层或表示层提供数据服务。

   业务逻辑层(BLL层):主要是针对具体的问题的操作,,对数据业务逻辑处理,或者理解成对数据层的操作。

    表示层(UI层):主要表示WEB方式,也可以表示成WINFORM方式,WEB方式也可以表现成:aspx, 作为展示。

1

  2.为什么要分三层?

答:使项目结构更清楚,分工更明确,有利于后期的维护和升级。它未必会提升性能,核心就是:修改表现层而不用修改逻辑层,修改逻辑层而不用修改数据层,有很多复杂的三层架构和多层架构,这里只做基本的三层架构描述。

      好处: 分工合作,开发人员可以专注于某一层;可移植性、模块化设计、重用性;支持分布式系统(基于网络)扩展性强; MSSQL、Oracle之间可以切换。

   接下来用话术脚本的例子做一下简单三层描述:

   话术脚本:又叫知识库,坐着对着电脑念给客户的东西,比如移动客户人员回答客户来电时用的一种文件。如图:

话术脚本

      开发步骤(顺序可变):
1)设计数据库表(DB);
2)设计取得各级数据的方法(DAL层);
3)设计界面,将表中的数据加载到TreeView中,为了能够在点击节点的时候将节点的正文填充到文本框中,因此将每个节点对应的Model           放到节点的Tag中(UI层)。
4)设计话术的添加、删除、修改、查找等功能(BLL业务逻辑层)。

    Model层:

public class T_Script
    {
        public int ScriptId { get; set; }
        public string ScriptTitle { get; set; }
        public string ScriptMsg { get; set; }
        public int ScriptParentId { get; set; }
    }

    Dal层(需SqlHelper.cs):

public class T_ScriptsDal
    {
        //选中类别显示该id的所有内容
        public T_Script GetScriptModelByScriptId(int sid)
        {
            T_Script model = null;
            string sql = "select * from T_Scripts where ScriptId=@sid";
            using (SqlDataReader reader = SqlHelper.ExecuteReader(sql, System.Data.CommandType.Text, new SqlParameter("@sid", sid)))
            {
                if (reader.HasRows)
                {
                    if (reader.Read())
                    {
                        model = new T_Script();
                        model.ScriptId = reader.GetInt32(0);
                        model.ScriptTitle = reader.GetString(1);
                        model.ScriptMsg = reader.GetString(2);
                        model.ScriptParentId = reader.GetInt32(3);
                    }
                }
            }
            return model;
        }
        //根据id获取数据库中的话术信息,供之后加载到treeview上
        public List<T_Script> GetScriptsByParentId(int pid)
        {
            List<T_Script> list = new List<T_Script>();
            string sql = "select ScriptId,ScriptTitle from T_Scripts where ScriptParentId=@pid";
            using (SqlDataReader reader = SqlHelper.ExecuteReader(sql, System.Data.CommandType.Text, new SqlParameter("@pid", pid)))
            {
                if (reader.HasRows)
                {
                    while (reader.Read())
                    {
                        T_Script model = new T_Script();
                        model.ScriptId = reader.GetInt32(0);
                        model.ScriptTitle = reader.GetString(1);
                        list.Add(model);
                    }
                }
            }
            return list;
        }
        //根据ScriptId查询Message:查询功能
        public string GetScriptMessageByScriptId(int sid)
        {
            string sql = "select ScriptMsg from T_Scripts where ScriptId=@sid";
            object obj = SqlHelper.ExecuteScalar(sql, System.Data.CommandType.Text, new SqlParameter("@sid", sid));
            return obj == null ? string.Empty : obj.ToString();

        }
         //添加功能
        public int Insert(T_Script model)
        {
            string sql = "insert into T_Scripts(ScriptTitle,ScriptMsg,ScriptParentId) values(@title,@msg,@pid)";
            SqlParameter[] pms = new SqlParameter[] {
            new SqlParameter("@title",model.ScriptTitle),
            new SqlParameter("@msg",model.ScriptMsg),
            new SqlParameter("@pid",model.ScriptParentId)
            };
            return SqlHelper.ExecuteNonQuery(sql, System.Data.CommandType.Text, pms);
        }
        //删除功能
        public int DeleteByScriptId(int sid)
        {
            string sql = "delete from T_Scripts where ScriptId=@sid";
            return SqlHelper.ExecuteNonQuery(sql, System.Data.CommandType.Text, new SqlParameter("@sid", sid));
        }
        //编辑修改功能
        public int Update(T_Script model)
        {
            string sql = "update T_Scripts set ScriptTitle=@title,ScriptMsg=@msg where ScriptId=@sid";
            SqlParameter[] pms = new SqlParameter[] {
            new SqlParameter("@title",model.ScriptTitle),
            new SqlParameter("@msg",model.ScriptMsg),
            new SqlParameter("@sid",model.ScriptId)
            };
            return SqlHelper.ExecuteNonQuery(sql, System.Data.CommandType.Text, pms);
        }

    }
}

     SqlHelper.cs

public static class SqlHelper
    {
        private static string conStr = ConfigurationManager.ConnectionStrings["coco"].ConnectionString;
        //增删改
        public static int ExecuteNonQuery(string sqlStr, CommandType ct, params SqlParameter[] sq)
        {
            using (SqlConnection sqlCon = new SqlConnection(conStr))
            {
                using (SqlCommand cmd = new SqlCommand(sqlStr, sqlCon))
                {
                    cmd.CommandType = ct;
                    if (sq != null)
                    {
                        cmd.Parameters.AddRange(sq);
                    }
                    //打开连接
                    sqlCon.Open();
                    return cmd.ExecuteNonQuery();
                }
            }
        }
        //scalar
        public static object ExecuteScalar(string sqlStr, CommandType ct, params SqlParameter[] sq)
        {
            using (SqlConnection sqlCon = new SqlConnection(conStr))
            {
                using (SqlCommand cmd = new SqlCommand(sqlStr, sqlCon))
                {
                    cmd.CommandType = ct;
                    if (sq != null)
                    {
                        cmd.Parameters.AddRange(sq);
                    }
                    //打开连接
                    sqlCon.Open();
                    return cmd.ExecuteScalar();
                }
            }
        }
        //reader
        public static SqlDataReader ExecuteReader(string sqlStr, CommandType ct, params SqlParameter[] sq)
        {
            SqlConnection sqlCon = new SqlConnection(conStr);
            using (SqlCommand cmd = new SqlCommand(sqlStr, sqlCon))
            {
                cmd.CommandType = ct;
                if (sq != null)
                {
                    cmd.Parameters.AddRange(sq);
                }
                //打开连接
                try
                {
                    sqlCon.Open();
                    return cmd.ExecuteReader(CommandBehavior.CloseConnection);
                }
                catch (Exception)
                {
                    sqlCon.Dispose();
                    throw;
                }
            }
        }
        //table
        public static DataTable ExecuteDataTable(string sqlStr, CommandType ct, params SqlParameter[] sq)
        {
            DataTable dt = new DataTable();
            using (SqlDataAdapter sda=new SqlDataAdapter(sqlStr,conStr))
            {
                sda.SelectCommand.CommandType = ct;
                if (sq != null)
                {
                    sda.SelectCommand.Parameters.AddRange(sq);
                }
                sda.Fill(dt);
                return dt;
            }
        }
    }
}

  BLL层:

 public class T_ScriptsBll
    {
         //引用Dal层并创建对象,开始业务逻辑层描述。
        T_ScriptsDal dal = new T_ScriptsDal();
        //根据id获取数据库中的话术信息,供UI层之后加载到treeview上
        public List<T_Script> GetScriptsByParentId(int pid)
        {
            return dal.GetScriptsByParentId(pid);
        }

        //根据ScriptId查询Message:查询功能
        public string GetScriptMessageByScriptId(int sid)
        {
            return dal.GetScriptMessageByScriptId(sid);
        }
        //添加功能
        public int Insert(T_Script model)
        {
            return dal.Insert(model);
        }

        //根据ScriptId删除一条记录:删除功能
        public int DeleteByScriptId(int sid)
        {
            return dal.DeleteByScriptId(sid);
        }

       //递归删除
        public void DiguiDeleteByScriptId(int sid)
        {
            //1.根据sid查询,并遍历
            List<T_Script> list = GetScriptsByParentId(sid);
            foreach (T_Script item in list)
            {
                DiguiDeleteByScriptId(item.ScriptId);
            }

            //2.删除当前的sid

            DeleteByScriptId(sid);
        }
        //编辑修改功能
        public int Update(T_Script model)
        {
            return dal.Update(model);
        }
        //创建model:选中类别显示该id的所有内容
        public T_Script GetScriptModelByScriptId(int sid)
        {
            return dal.GetScriptModelByScriptId(sid);
        }
    }
}

    UI层:

    父窗口:

public partial class frmScripts : Form
    {
        public frmScripts()
        {
            InitializeComponent();
        }
        private void UpdateEditNode(string title, string message)
        {
            if (treeView1.SelectedNode != null)
            {
                treeView1.SelectedNode.Text = title;
                txtMessage.Text = message;
            }
        }
        //窗体加载事件:委托
        private void frmScripts_Load(object sender, EventArgs e)
        {
            RefreshTreeView();
        }
        private void RefreshTreeView()
        {
            treeView1.Nodes.Clear();
            //加载类别到TreeView
            LoadScriptTitleToTree(0, treeView1.Nodes);
        }
        //引用BLL层,并创建对象
        T_ScriptsBll bll = new T_ScriptsBll();
        //查询后加载
        private void LoadScriptTitleToTree(int pid, TreeNodeCollection treeNodeCollection)
        {
            //1.根据pid查询数据
            List<T_Script> list = bll.GetScriptsByParentId(pid);


            //2.把查询到的数据绑定到treeNodeCollection集合中
            foreach (var itemScript in list)
            {
                TreeNode tnode = treeNodeCollection.Add(itemScript.ScriptTitle);
                tnode.Tag = itemScript.ScriptId;
                //递归
                LoadScriptTitleToTree(itemScript.ScriptId, tnode.Nodes);
            }
        }
        //TreeView的节点的选中后触发的事件
        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            //1.获取选中节点
            if (e.Node != null)
            {
                //2.获取选中个节点中的ScriptId
                int scriptId = (int)e.Node.Tag;


                //3.根据ScriptId查询对应的ScriptMsg
                T_ScriptsBll bll = new T_ScriptsBll();

                //4.将查询到的ScriptMsg赋值给右侧的文本框
                txtMessage.Text = bll.GetScriptMessageByScriptId(scriptId);
            }
        }
        //添加功能:1
        private void 增加一级类别ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            frmAddScripts frmScripts = new frmAddScripts(RefreshTreeView, 0);
            frmScripts.Show();
        }
        //添加功能:2
        private void 在选中的类别下增加子类别ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (treeView1.SelectedNode != null)
            {
                frmAddScripts frmScripts = new frmAddScripts(RefreshTreeView, (int)treeView1.SelectedNode.Tag);
                frmScripts.Show();
            }
            else
            {
                MessageBox.Show("请选中节点!");
            }
        }
        //删除功能:删除选中的TreeView节点
        private void 删除选中类别ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (treeView1.SelectedNode != null)
            {
                int sid = (int)treeView1.SelectedNode.Tag;
                //执行删除
                T_ScriptsBll bll = new T_ScriptsBll();
                bll.DiguiDeleteByScriptId(sid);

                //从界面上删除
                treeView1.SelectedNode.Remove();
            }
        }
        //编辑修改功能
        private void 编辑ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //1.先判断是否有选中节点
            if (treeView1.SelectedNode != null)
            {
                int sid = (int)treeView1.SelectedNode.Tag;
                //显示编辑窗口
                frmScriptEdit frmEdit = new frmScriptEdit(sid, UpdateEditNode);
                frmEdit.Show();
            }
            else
            {
                MessageBox.Show("请选中节点!");
            }
        }
        //搜索功能:展示
        //在TreeView上进行节点搜索
        private void tsmiSearchBtn_Click(object sender, EventArgs e)
        {
            //将TreeView的所有节点都合上。
            treeView1.CollapseAll();
            string search = tsTextSearch.Text.Trim();

            //递归搜索节点
            SearchNodeText(search, treeView1.Nodes);
        }
        //搜索功能
        private void SearchNodeText(string search, TreeNodeCollection treeNodeCollection)
        {
            foreach (TreeNode item in treeNodeCollection)
            {
                if (item.Text.Contains(search))
                {
                    item.BackColor = Color.Red;
                    //确保当前节点可见。用户可以看得到,其实就是把相关的父节点都展开。
                    item.EnsureVisible();
                }
                else
                {
                    item.BackColor = Color.White;
                }
                //递归搜索
                SearchNodeText(search, item.Nodes);
            }
        }
    }
}

    子窗口:增加功能

 public partial class frmAddScripts : Form
    {
        //增加功能:子窗口
        public frmAddScripts()
        {
            InitializeComponent();
        }
       //委托传递:保证子窗口添加后,父窗口可以同时刷新treeview同步显示增加后结果
        public frmAddScripts(Action method, int pid)
            : this()
        {
            this._refreshTree = method;
            this._parentId = pid;
        }
        private int _parentId;
        //定义无参数无返回值的委托
        private Action _refreshTree;
        //增加的按钮事件:
        private void button1_Click(object sender, EventArgs e)
        {
            //1.采集数据
            T_Script model = new T_Script();
            model.ScriptTitle = txtTitle.Text.Trim();
            model.ScriptMsg = txtMessage.Text.Trim();
            model.ScriptParentId = _parentId;
            //2.调用业务逻辑层实现增加一条话术脚本
            T_ScriptsBll bll = new T_ScriptsBll();
            bll.Insert(model);
            if (_refreshTree != null)
            {
                //刷新父窗口中的TreeView
                _refreshTree();
            }
            this.Close();
        }
    }
}

    子窗口:编辑修改

    public partial class frmScriptEdit : Form
    {
        private int sid;
        //编辑修改功能:子窗口
        public frmScriptEdit()
        {
            InitializeComponent();
        }
        //委托传递
        public frmScriptEdit(int sid, Action<string, string> method)
            : this()
        {
            // TODO: Complete member initialization
            this.sid = sid;
            _updateNode = method;
        }
        //定义委托:有两个参数
        private Action<string, string> _updateNode;
        //执行更新操作
        private void button1_Click(object sender, EventArgs e)
        {
            //1.采集数据
            T_Script model = new T_Script();
            model.ScriptId = this.sid;
            model.ScriptTitle = txtTitle.Text.Trim();
            model.ScriptMsg = txtMessage.Text.Trim();
            //2.调用业务逻辑层执行更新操作
            T_ScriptsBll bll = new T_ScriptsBll();
            bll.Update(model);

            if (_updateNode != null)
            {
                //通过委托更新主窗口中的TreeView节点。
                _updateNode(model.ScriptTitle, model.ScriptMsg);
            }
            this.Close();
        }
        //窗体加载
        private void frmScriptEdit_Load(object sender, EventArgs e)
        {
            //现根据要更新的记录的sid,获取该记录的最新的内容填充到文本框中
            LoadEditInfo();
        }
        private void LoadEditInfo()
        {
            T_ScriptsBll bll = new T_ScriptsBll();
            T_Script model = bll.GetScriptModelByScriptId(this.sid);
            if (model != null)
            {
                this.txtTitle.Text = model.ScriptTitle;
                this.txtMessage.Text = model.ScriptMsg;
            }
            else
            {
                throw new Exception("不存在该记录!");
            }
        }
    }
}

Written by

说点什么

欢迎讨论

avatar

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

  Subscribe  
提醒