zoukankan      html  css  js  c++  java
  • CYQ.Data 轻量数据层之路 应用示例二 在线聊天(六)

    继上一篇:CYQ.Data 轻量数据层之路 华丽升级 V1.3出世(五),本篇趁周末而且是下班时间看贴人不多,低调让其出手应用一下:

    同样为了能一篇介绍完一个示例,我精简挑选了一下,本次的示例为:注册+登陆+在线聊天[省去了私聊部分]

    在看此文示例之前,请先看:CYQ.Data 轻量数据层之路 应用示例篇(四) --因为注册+登陆从那直接Copy的,这节就省过了。

    当前环境同样是:VS2005+SQL2005,以下进入正题:

    一:数据库

    起名:Chat

    两个表:Users+Message,上图:

    说明:和上一示例比较:Users表是一样的,Message表也几乎一样了。

    二:项目初始

    1:新建网站项目,如起名叫:Cyq.Data.ChatDemoProject

    同样产生webconfig后添加好数据库链接!

    2:添加引用:CYQ.Data.dll

    3:生成分页查询存储过程与枚举:还是页面:WriteOut.aspx,用于生成输出:

    生成分页存储过程新方法:CYQ.Data 轻量数据层之路 华丽升级 V1.3出世(五):[9:OutPutData:增加ExeCreateProc方法用于直接执行生成分页存储过程]

    三:项目开始:

    先上图,整体项目情况:

    1:注册用户(Login.aspx:见示例篇(四))

    2:用户登陆(Reg.aspx:见示例篇(四))

    3:在线聊天:(Default.aspx)

    先上图,聊天主界面:

    分区域说明:

    1:左侧区为聊天显示区
    2:右侧上头为欢迎与退出
    3:右侧下头为用户列表区
    4:底部就是留言区了
    5:ajax定时刷新用2.0内置ICallBack接口实现。

    下面进行代码解说:

    页面进来时,把能加载的都加载完:只有三个点[1:登陆者名称;2:用户列表;3:默认取10条留言显示]

    1:登陆者名称与退出事件

        void LoadMyInfo()
        {
            
    if (Session["ID"== null)
            {
                Response.Redirect(
    "Login.aspx");
            }
            
    else
            {
                Session[
    "ID"= Session["ID"];
                myID 
    =Convert.ToInt32(Session["ID"]);
                MAction action 
    = new MAction(TableNames.Users);
                
    if (action.Fill(myID))
                {
                    action.SetTo(labUserName);
                }
                
    else
                {
                    labUserName.Text 
    = "读取数据失败!";
                }
                action.Close();
            }
        }
        
    protected void btnLogout_Click(object sender, EventArgs e)
        {
            Session[
    "ID"= null;
            Response.Redirect(
    "Login.aspx");
        }

    2与3:绑定用户列表与后十条留言

        void LoadListInfo()
        {
            
    int rowCount;
            MAction action 
    = new MAction(TableNames.Users);//加载用户列表
            rptUserList.DataSource = action.Select(0,0,"ID<>"+myID,out rowCount);
            rptUserList.DataBind();
            
    if (action.ResetTable(CustomerSQL.Message))//切换表到留言列表,加载留言列表
            {
                rptMessageList.DataSource 
    = action.Select(110""out rowCount);
                rptMessageList.DataBind();
                action.Close();
            }
        }

    上面又有一个自定义的CustomerSQL.Message,其实我应该用一下存储过程来演示的,算了,写都写了:

    还是和上次演示一下,自定义语句放到类里统一管理了:

    /// <summary>
    /// by 路过秋天 http://cyq1162.cnblogs.com/
    /// </summary>
    public class CustomerSQL
    {
        
    public const string Message = "(SELECT m.*,uA.UserName,isnull(uB.UserName,'所有人') AS UserName2 FROM Message m LEFT JOIN Users uA ON m.SendUserID=uA.ID LEFT JOIN Users uB ON m.RecvUserID=uB.ID) v";
    }

    4:接下来是Ajax部分了

    这里我封装了一下,新建了个PageBase类放里面了,看一下PageBase.cs代码:

    /// <summary>
    /// 路过秋天 http://cyq1162.cnblogs.com
    /// </summary>
    public class PageBase:System.Web.UI.Page,ICallbackEventHandler
    {
        
    #region ICallbackEventHandler 成员
        
    /// <summary>
        
    /// Ajax方法时的回调结果
        
    /// </summary>
        public string ajaxCallBackResult = null;
        
    /// <summary>
        
    /// 注册Ajax方法
        
    /// 调用方法名:callAjax(arg)
        
    /// 回调方法名:callBack(result)
        
    /// </summary>
        public void RegisterAjax()
        {
            RegisterAjax(
    this"callAjax""callBack");
        }
        
    public void RegisterAjax(Control ct, string functionName, string callBackName)
        {
            
    if (!ct.Page.ClientScript.IsClientScriptBlockRegistered(functionName))
            {
                
    string callBack = ct.Page.ClientScript.GetCallbackEventReference(ct, "arg", callBackName, null);
                
    string clientFunction = "function " + functionName + "(arg){" + callBack + "}";
                ct.Page.ClientScript.RegisterClientScriptBlock(ct.Page.GetType(), functionName, clientFunction, 
    true);
            }
        }
        
    public string GetCallbackResult()
        {
            
    return ajaxCallBackResult;
        }
        
    public virtual void RaiseCallbackEvent(string eventArgument)
        {
            
        }
        
    public virtual void RegisterCommonScript()
        {
            
    const string script = @"function $(id){return document.getElementById(id)}function $V(id,defaltValue){if($(id)){if(defaltValue && $(id).value.length==0){return defaltValue;} else{return $(id).value;}}return '';}";

            Page.ClientScript.RegisterClientScriptBlock(
    this.Page.GetType(), "GetBy", script, true);
        }
        
    #endregion
    }

    OK,现在看一下Default.aspx的Page_Load里调用一下:

    public partial class _Default :PageBase
    {
        
    int myID;
        
    protected void Page_Load(object sender, EventArgs e)
        {
            LoadMyInfo();
            LoadListInfo();
            RegisterCommonScript();
            RegisterAjax();
        }
    //...省略N行代码...
    }

    其实,Ajax只有两部分:

    1:点提交时,用户消息要ajax提交到后台入库:
    2:用户定时去取消息

    关于这两个,我们看一下ICallBack的实现:

    public override void RaiseCallbackEvent(string eventArgument)
        {
            
    int splitIndex = eventArgument.IndexOf(':');
            
    string cmd = eventArgument.Substring(0, splitIndex);
            
    string data = eventArgument.Substring(splitIndex+1);
            
    switch (cmd)
            {
                
    case "0"://送发消息
                    ajaxCallBackResult = "0☆" + Send(data);
                    
    break;
                
    case "1"://查询消息
                    ajaxCallBackResult = "1☆" + GetMessage(data);
                    
    break;
            }
        }

    接收时:该代码和前台html约定好分隔符,这里为“:”号;

    返回时:也要约定好分隔符,这里为“”号;

    接下来就是实现两个函数Send与GetMessage了。

    看下Send:

     string Send(string msg)
        {
            
    int splitIndex=msg.IndexOf(':');
            
    string[] content = msg.Split('');//内容为接收者ID☆消息内容
             MAction action = new MAction(TableNames.Message);
            action.Set(Message.SendUserID, myID);
            action.Set(Message.RecvUserID,msg.Substring(
    0,splitIndex));
            action.Set(Message.Body, msg.Substring(splitIndex
    +1));
            
    string result = action.Insert() ? "1" : "0";
            
    return result;
        }

    再看下GetMessage:

    private const string msg = "<div class=\"msg\"><font color=\"Olive\">{0}</font> 对 <font color=\"Olive\">{1}</font> 说 <font color=\"Olive\">{2}</font><br /><p>{3}</p></div>";
        
    string GetMessage(string maxID)
        {
            
    string result="";
            MAction action 
    = new MAction(CustomerSQL.Message);
            
    if (maxID =="0")
            {
                
    if (action.Fill("1=1 order by id desc"))//取最大ID返回
                {
                    result 
    = action.Get<string>(Message.ID)+"";
                    action.Close();
                }
            }
            
    else
            {
                
    int rowCount;
                MDataTable mTable 
    = action.Select(00string.Format("ID>{0} and SendUserID<>{1} and (RecvUserID=0 or RecvUserID={1})", maxID, myID), out rowCount);
                action.Close();
                
    if (rowCount > 0)
                {
                    result 
    = mTable.Rows[rowCount - 1]["ID"].Value + "";
                    
    foreach (MDataRow row in mTable.Rows)
                    {
                        result 
    += string.Format(msg,row["UserName"].Value, row["UserName2"].Value,row["PubTime"].Value,row["Body"].Value);
                    }
                }
                
    else
                {
                    result 
    += maxID + "";
                }
            }
            
    return result;
        }

    代码有点长,似乎不太好理解,因为和前台html界面相关的关系:其实就是组合字符串输出了。

    5:前台HTML/JS

    发送消息时:

    //组合成 命令:用户ID:留言内容
    callAjax("0:"+$V('hdfUserID')+":"+$('txtBody').innerHTML);

    接收消息时:

    //组合成 命令:最大消息ID
    callAjax("1:"+msgMaxID);

    回调时结果:

        function callBack(result)
        {
           var  items=result.split('☆');     
            switch(items[0])
            {
                case "0"://发送消息返回结果
                    $('btnSend').disabled=false;
                    add($V('hdfBody'));
                    break;
                case "1"://查询返回结果
                    if(items.length>1)
                    {
                        msgMaxID=items[1];
                    }
                    if(items.length>2)
                    {
                        add(items[2]);
                    }
                    break;
            }
       }
       function add(msg)
       {
            if(msg)
            {
                 $('left').innerHTML+=msg;
                 $('left').scrollTop=$('left').scrollHeight;//滚动条定位到最后面
            }
       }

    其余具体html代码就不详细贴出来了,因为我知道,我上面代码贴的再详细,估计也没多少人看,大伙看个开头,然后往下拉,看到源码下载,点击下载,差不多就拍拍屁股走人了

    不过还是要提供整个示例下载:点击下载 [数据库创建脚本在App_Data目录下]

     欢迎感兴趣读者讨论与留言:[上面代码注释太少,在测试使用中,如有不明请留言]。[写个示例花了1小时,写篇文章花了一天了,不容易啊!]

    版权声明:本文原创发表于 博客园,作者为 路过秋天 本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。
    个人微信公众号
    创业QQ群:617713515
    Donation(扫码支持作者):支付宝:
    Donation(扫码支持作者):微信:
  • 相关阅读:
    [hdu-2048] 神、上帝以及老天爷
    or1200中IMMU分析(续)
    Java Applet读写client串口——终极篇
    树莓派_Linux串口编程_实现自发自收
    2014百度实习生面试题(部分)具体解释
    Leetcode
    eclipse+webservice开发实例
    现有一些开源ESB总线的比較
    《HTML5 从入门到精通--7.6.3 单元格垂直跨度——rowspan》
    百度究竟是哪国的公司
  • 原文地址:https://www.cnblogs.com/cyq1162/p/1805018.html
Copyright © 2011-2022 走看看