代码改变世界

基于atlas的聊天室设计(有源码)

2007-06-12 14:19  Brush  阅读(609)  评论(4编辑  收藏  举报

  来博客园有一段时间了,觉得这里高手蛮多的,也能学到不少东西。
  最近我在搞一个B/S结构下的聊天室,用到了atlas技术,其中也有点小问题,就是输入框的焦点会在局部刷新的时候丢失。望各高手不吝赐教。
  
  首先说一下我的设计思路:
  在B/S下的聊天室,因为服务端不能主动向客户端发送消息(请求),只能响应客户端发送过来的请求,故聊天室的聊天数据的获取只能是主动形式的,即客户端定期向服务端请求最新聊天数据,然后显示在页面上。这样就不得不涉及到页面的频繁刷新。在刷新方面我用了atlas局部刷新技术。
  数据存取方面我使用了NHibernate技术。
  此聊天室是一个功能很简单的聊天室,源码如下:

  页面部分:

  1<%@ Page Language="C#" AutoEventWireup="true" CodeFile="zDefault.aspx.cs" Inherits="_Default" validateRequest=false %>
  2
  3<html xmlns="http://www.w3.org/1999/xhtml">
  4<script type="text/javascript" language="JavaScript"> 
  5function   document.onkeydown()     
  6{     
  7  var   e=event.srcElement;     
  8  if((event.keyCode==13)   &&   event.ctrlKey)     
  9  {     
 10  document.getElementById("btnSend").click();
 11  return   false;     
 12  }

 13}
;
 14function beforeunloads()
 15{
 16//    if(confirm('确认退出《刷刷聊天室》?') == false)
 17//    {
 18////        document.getElementById("btnExit").click();
 19//       cancel=1;
 20//       return false;
 21//    }
 22//    cancel=1;
 23//    return true;
 24if  (event.clientX>document.body.clientWidth  &&  event.clientY<0 || event.altKey)  
 25           
 26                       window.event.returnValue="确认退出《刷刷聊天室》?";  
 27           }
 
 28}
;
 29 
</script>
 30<head runat="server">
 31    <title>刷刷聊天室</title>
 32</head>
 33<body onbeforeunload="javascript:beforeunloads();">
 34    <form id="form1" runat="server">
 35        <atlas:ScriptManager ID="ScriptManager1" EnablePartialRendering=true runat="server" />
 36        <atlas:UpdateProgress ID=upup1 runat=server>
 37            
 38            <ProgressTemplate>
 39                <label id="aaa" runat=server>正在更新信息</label><asp:TextBox ID="TextBox1" runat="server">aaa</asp:TextBox>
 40            </ProgressTemplate>
 41        </atlas:UpdateProgress>
 42       <%-- <atlas:TimerControl ID=tt1 runat=server OnTick=btnRefresh_Click EnableViewState=true Interval=5000></atlas:TimerControl>--%>
 43        
 44            <span style="color: mediumblue"><strong>欢迎进入刷刷聊天室</strong><span style="color: red"></span><span style="color: red"></span><strong>
 45                    <asp:Button ID="btnExit" runat="server" OnClientClick="return confirm('确认退出刷刷聊天室?')" OnClick="btnExit_Click" Text="退 出" /></strong></span><br />
 46                    
 47         
 48             <atlas:UpdatePanel ID="up1" runat="server" RenderMode=Block Mode="conditional">
 49        <ContentTemplate>
 50            <strong><span style="color: #0000cd">(</span></strong><span style="color: red">当前共<asp:Label
 51                ID="lblNum" runat="server"></asp:Label><strong><span style="color: #0000cd">)</span><asp:Button
 52                    ID="btnRefresh" runat="server" OnClick="btnRefresh_Click" Text="0" Width="100px" /><br />
 53                    <br />
 54                </strong></span>&nbsp; 我的呢称:<asp:Label ID="Label2" runat="server" Text="Label"></asp:Label>
 55                <asp:TextBox ID="txtName" runat="server"></asp:TextBox>
 56                <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="修 改" TabIndex="1" />
 57            <br />
 58            &nbsp; 信息序号:<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label><br />
 59        
 60            <div id="divMain" runat="server" style="border-right: blue 1px solid; padding-right: 5px;
 61                border-top: blue 1px solid; padding-left: 5px; font-size: 12px; padding-bottom: 5px;
 62                overflow: auto; border-left: blue 1px solid; width: 735px; padding-top: 5px; word-break:break-all;
 63                border-bottom: blue 1px solid; height: 223px">
 64            </div>
 65            &nbsp;&nbsp;
 66            <asp:Button ID="btnClear" runat="server" OnClick="btnClear_Click" Text="清 屏" />&nbsp;<br />
 67            <br />
 68            &nbsp; 对<asp:DropDownList ID="ddlPerson" runat="server">
 69            </asp:DropDownList>说:<br />
 70            &nbsp;
 71            <asp:TextBox ID="txtInput" runat="server" Height="103px" TextMode="MultiLine" Width="534px"></asp:TextBox><br />
 72            &nbsp;
 73            <asp:Button ID="btnSend" runat="server" OnClick="btnSend_Click" Text="发 送(Ctrl+Enter)" />&nbsp;
 74                <%--<a href=Default.aspx target=_blank>aa</a>--%>
 75            <br />
 76            </ContentTemplate>
 77            <Triggers>
 78                <atlas:ControlEventTrigger ControlID="btnSend" EventName="Click" />
 79                <atlas:ControlEventTrigger ControlID="Button1" EventName="Click" />
 80                <%--<atlas:ControlEventTrigger ControlID="btnRefresh" EventName="Click" />--%>
 81                <atlas:ControlEventTrigger ControlID="btnClear" EventName="Click" />
 82                <atlas:ControlValueTrigger ControlID="Label1" PropertyName="Text" />
 83                <atlas:ControlValueTrigger ControlID="Label2" PropertyName="Text" />
 84                <atlas:ControlValueTrigger ControlID="txtInput" PropertyName="Text" />
 85                <atlas:ControlValueTrigger ControlID="ddlPerson" PropertyName="SelectedIndex" />
 86            </Triggers>
 87        </atlas:UpdatePanel>
 88        
 89    </form>
 90</body>
 91<script language=javascript type="text/javascript">
 92//var txtabc = "txtInput";
 93//var tempabc = document.getElementById("txtInput");
 94//    tempabc.onfocus() = function() { txtabc = "txtInput";};
 95//    tempabc = document.getElementById("txtName");
 96//    tempabc.onfocus() = function() { txtabc = "txtName";};
 97//function settxtabc(tt)
 98//{
 99//    txtabc = tt;
100//}
101function   mainRefresha()     
102{
103  // 记录光标丢失位置
104  document.getElementById("btnRefresh").click();
105  // 恢复原光标位置
106  document.getElementById("txtInput").innerText = "abc";
107  return true;
108}
;
109function northsnow()
110{
111//    document.getElementById(txtabc).focus();
112    divMain.scrollTop=divMain.scrollHeight;
113    setTimeout("mainRefresha()",5000);
114}
;
115//setInterval('northsnow()',100);
116setTimeout("northsnow()",1);
117
</script>
118</html>

后.cs部分:
 

  1public partial class _Default : System.Web.UI.Page 
  2{
  3    protected void Page_Load(object sender, EventArgs e)
  4    {
  5        if (!IsPostBack)
  6        {
  7            if (btnRefresh.Text == "0")
  8            {
  9                //txtInput.Attributes.Add("onclick", "settxtabc('txtInput')");
 10                //txtName.Attributes.Add("onclick", "settxtabc('txtName')");
 11                ViewState["id"= VCwMess.GetLastID().ToString();
 12                btnRefresh.Text = "1";
 13                Label2.Text = "游客" + DateTime.Now.ToString("HHmmssfff");
 14                AddUser(Label2.Text);
 15                ViewState["userRefresh"= DateTime.Now;
 16                RefreshUsers(); // 刷新用户列表
 17            }

 18        }

 19    }

 20
 21    // 修改呢称
 22    protected void Button1_Click(object sender, EventArgs e)
 23    {
 24        //System.Threading.Thread.Sleep(2000); // 网络延迟
 25        CwUser cc = VCwUser.GetById(((CwUser)(ViewState["user"])).Id);
 26        cc.Name = txtName.Text;
 27        cc.Lasttime = DateTime.Now;
 28        VCwUser.SaveOrUpdate(cc);
 29        ViewState["user"= cc;
 30        AddMess(3, Label2.Text, txtName.Text, cc.Id.ToString(), false);
 31        Label2.Text = txtName.Text;
 32    }

 33
 34    // 发送信息
 35    protected void btnSend_Click(object sender, EventArgs e)
 36    {
 37        //System.Threading.Thread.Sleep(2000); // 网络延迟
 38        //AddMess(0, Label2.Text, ddlPerson.SelectedValue, txtInput.Text, true);
 39        CwUser cc = VCwUser.GetById(((CwUser)(ViewState["user"])).Id);
 40        cc.Lasttime = DateTime.Now;
 41        VCwUser.SaveOrUpdate(cc);
 42        ViewState["user"= cc;
 43        AddMess(0, Label2.Text, ddlPerson.SelectedItem.Text, txtInput.Text, true);
 44        //this.ClientScript.RegisterClientScriptBlock(this.GetType(), "yimi", "setTimeout('northsnow()',100);", true);
 45        //this.ClientScript.RegisterClientScriptBlock(this.GetType(), "yimi", "document.getElementById('txtInput').focus();", true);
 46        //txtName.Focus();
 47        //txtInput.Focus();
 48    }

 49
 50    // 设置/刷新聊天窗口显示
 51    private void SetMain()
 52    {
 53        //IList list = VCwMess.GetList(DateTime.Now.AddSeconds(-10));
 54        int id = int.Parse(ViewState["id"].ToString());
 55        IList list = VCwMess.GetList(id);
 56       
 57        foreach (CwMess cc in list)
 58        {
 59            if (cc.Id > id)  // 表明此信息未被加载
 60            {
 61                ShowMess(cc); // 加载此信息
 62            }

 63        }

 64        Label1.Text = ViewState["id"].ToString();
 65        this.ClientScript.RegisterClientScriptBlock(this.GetType(), "yimi""setTimeout(\"northsnow()\",1);"true);
 66        //this.ClientScript.RegisterClientScriptBlock(this.GetType(), "yimi", "setTimeout(\"northsnow('" + ViewState["txt"].ToString() + "')\",1);", true);
 67        //this.ClientScript.RegisterClientScriptBlock(this.GetType(), "yimi", "document.all('txtInput').focus();", true);
 68        //this.ClientScript.RegisterStartupScript(typeof(Microsoft.Web.UI.UpdatePanel), "yimi1", "document.getElementById('txtInput').focus();", true);
 69        //Response.Write("<script>divMain.scrollTop=divMain.scrollHeight;</script>");
 70    }

 71
 72    // 刷新用户列表(在用户登录之后)
 73    private void RefreshUsers()
 74    {
 75        ddlPerson.Items.Clear();
 76        ddlPerson.Items.Add(new ListItem("所有人""0"));
 77
 78        IList list = VCwUser.GetList(DateTime.Now.AddMinutes(-10)); // 读取10分钟内都在发言的名单(某人关闭页面后,10分钟才能体现出来)
 79        lblNum.Text = list.Count.ToString();
 80        int id = ((CwUser)(ViewState["user"])).Id;
 81        foreach (CwUser cc in list)
 82        {
 83            if (cc.Id != id)  // 下拉菜单中只添加其它人
 84            {
 85                ddlPerson.Items.Add(new ListItem(cc.Name, cc.Id.ToString()));
 86            }

 87        }

 88    }

 89
 90    // 刷新聊天信息
 91    protected void btnRefresh_Click(object sender, EventArgs e)
 92    {
 93        System.Threading.Thread.Sleep(2000); // 网络延迟
 94        SetMain();
 95        if (ViewState["userRefresh"== null)
 96        {
 97            ViewState["userRefresh"= DateTime.Now;
 98            RefreshUsers(); // 刷新用户列表
 99        }

100        else
101        {
102            DateTime dt = (DateTime)(ViewState["userRefresh"]);
103            if (dt.AddMinutes(5< DateTime.Now)  // 五分钟刷新一次列表(同时对无操作的本用户更新状态)
104            {
105                // 对无操作的本用户更新状态
106                CwUser cc = VCwUser.GetById(((CwUser)(ViewState["user"])).Id);
107                cc.Name = txtName.Text;
108                cc.Lasttime = DateTime.Now;
109                VCwUser.SaveOrUpdate(cc);
110                ViewState["user"= cc;
111
112                ViewState["userRefresh"= DateTime.Now;
113                RefreshUsers(); // 刷新用户列表
114            }

115        }

116    }

117
118    // 添加一条信息
119    private void AddMess(int type, string from, string to, string mess, bool needClear)
120    {
121        CwMess cc = new CwMess();
122        cc.Name1 = from;
123        cc.Name2 = to;
124        cc.Inf = mess;
125        cc.AddTime = DateTime.Now;
126        cc.Type = type; // 一般消息
127        if (needClear) // 需要清除输入框
128        {
129            txtInput.Text = "";
130        }

131
132        VCwMess.SaveOrUpdate(cc);
133        SetMain();
134    }

135
136    // 添加一个用户
137    private void AddUser(string name)
138    {
139        CwUser cc = new CwUser();
140        cc.Name = Label2.Text;
141        cc.State = 1;
142        VCwUser.SaveOrUpdate(cc);
143        ViewState["user"= cc;
144        AddMess(2, cc.Name, cc.Id.ToString(), ""false);
145        
146        
147    }

148
149    // 显示一条信息
150    private void ShowMess(CwMess cc)
151    {
152        string temp;
153        switch (cc.Type)
154        {
155            case 0:  // 一般消息
156                temp = "[<font color=blue>" + cc.Name1 + "</font>] 对 [<font color=blue>" + cc.Name2 + "]</font> 说:";
157                temp += "<font color=gray>" + cc.AddTime.ToString("HH:mm:ss"+ "<br> ";
158                temp += cc.Inf;
159                temp += "<br>";
160                break;
161            case 1:  // 系统公告
162                temp = "<br>[<b><font color=red>系统公告</font></b>]" + "<font color=gray>" + cc.AddTime.ToString("HH:mm:ss"+ "<br> ";
163                temp += "<font color=red>" + cc.Inf + "</font><br>";
164                break;
165            case 2:  // 进入聊天室
166                temp = "<br>[<b><font color=red>系统公告</font></b>]" + "<font color=gray>" + cc.AddTime.ToString("HH:mm:ss"+ "<br> ";
167                temp += "欢迎[<font color=blue>" + cc.Name1 + "</font>] 进入刷刷聊天室!<br>";
168                if(((CwUser)(ViewState["user"])).Id.ToString() != cc.Name2)  // 不是本人的消息
169                {
170                    ddlPerson.Items.Add(new ListItem(cc.Name1, cc.Name2));
171                    int num = ddlPerson.Items.Count + 1;
172                    lblNum.Text = num.ToString();
173                }

174                break;
175            case 3// 更改呢称
176                temp = "<br>[<b><font color=red>系统公告</font></b>]" + "<font color=gray>" + cc.AddTime.ToString("HH:mm:ss"+ "<br> ";
177                temp += "[<font color=blue>" + cc.Name1 + "</font>] 更改呢称为:[<font color=blue>" + cc.Name2 + "</font>]<br>";
178                if (((CwUser)(ViewState["user"])).Id.ToString() != cc.Inf)  // 不是本人的消息
179                {
180                    for (int i = 0; i < ddlPerson.Items.Count; i++)
181                    {
182                        if (ddlPerson.Items[i].Value == cc.Inf)
183                        {
184                            ddlPerson.Items.RemoveAt(i);
185                            ddlPerson.Items.Add(new ListItem(cc.Name2, cc.Inf));
186                            break;
187                        }

188                    }

189                }

190                break;
191            case 4// 离开聊天室
192                temp = "<br>[<b><font color=red>系统公告</font></b>]" + "<font color=gray>" + cc.AddTime.ToString("HH:mm:ss"+ "<br> ";
193                temp += "[<font color=blue>" + cc.Name1 + "</font>] 离开了。<br>";
194                lblNum.Text = ddlPerson.Items.Count.ToString();
195                ddlPerson.Items.Remove(ddlPerson.Items.FindByText(cc.Name1)); // 从下拉列表中移除
196                break;
197            default:
198                temp = "<b><font color=red>系统出错!请联系管理员!</font></b>" + "<font color=gray>" + cc.AddTime.ToString("HH:mm:ss"+ "<br>";
199                break;
200        }

201        divMain.InnerHtml += temp;
202        ViewState["id"= cc.Id;
203    }

204
205    // 退出聊天室
206    protected void btnExit_Click(object sender, EventArgs e)
207    {
208        string url = "Logout.aspx?id=" + ((CwUser)(ViewState["user"])).Id.ToString();
209        Response.Write("<script>location.href='" + url + "';self.opener='meizz';self.close();</script>");
210    }

211
212    // 清屏
213    protected void btnClear_Click(object sender, EventArgs e)
214    {
215        //System.Threading.Thread.Sleep(2000); // 网络延迟
216        divMain.InnerHtml = "";
217    }

218}

 需要创建的表:

CREATE TABLE [dbo].[mess] (
    
[Id] [int] IDENTITY (11NOT NULL ,
    
[type] [int] NULL ,
    
[inf] [text] COLLATE Chinese_PRC_CI_AS NULL ,
    
[name1] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,
    
[name2] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,
    
[addtime] [datetime] NULL 
ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

CREATE TABLE [dbo].[users] (
    
[Id] [int] IDENTITY (11NOT NULL ,
    
[name] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,
    
[lasttime] [datetime] NULL ,
    
[state] [int] NULL 
ON [PRIMARY]
GO



源代码下载:https://files.cnblogs.com/yimi329/ChatRoom.rar