基于的C/S模式单机版的考试系统,我记得那种单机版的考试系统在进入考试以后界面就会自动的最大化,从而使考生的界面只能停留在考试界面而不能进行其他的操作,那样的话保证了考试系统的安全性。那么现在基于B/S模式下的在线考试系统的考试倒计时应该怎么样做了。为了比较性的说明问题,我先把我的具体做法写下来,大家一起来分析分析:
1.第一种方法:
我采用的是JavaScript来实现的
设计思想:在客户端加载页面时调用一段JS代码,在这段代码中设置一个函数,获取当前时间,并每隔一秒调用以此该函数。
编写代码如下:
1 <html xmlns="http://www.w3.org/1999/xhtml">
2 <head>
3 <script language="javascript">
4 var timerID = null;
5 var timerRunning = false;
6 var leftsec = 0;
7 var leftmin = 2;
8 var lefthour = 0;
9 function stopclock() {
10 if (timerRunning)
11 clearTimeout(timerID);
12 timerRunning = false;
13 }
14 function startclock() {
15 stopclock();
16 showtime();
17 }
18 function showtime() {
19 var now = new Date();
20 var hours = now.getHours();
21 var minutes = now.getMinutes();
22 var seconds = now.getSeconds();
23 var timeValue = now.getYear() + "年" + (now.getMonth() + 1) + "月" + now.getDate() + "日" + ((hours >= 12) ? " 下午 " : " 上午 ");
24 var lefttime = ((hours > 12) ? hours - 12 : hours) + ((minutes < 10) ? "小时0" : "小时") + minutes + ((seconds < 10) ? "分0" : "分") + leftsec + "秒";
25 timeValue += ((hours > 12) ? hours - 12 : hours);
26 timeValue += ((minutes < 10) ? ":0" : ":") + minutes;
27 timeValue += ((seconds < 10) ? ":0" : ":") + seconds;
28 document.getElementById('thetime').innerHTML = timeValue;
29 timerID = setTimeout("showtime()", 500);
30
31 timerRunning = true;
32 }
33 </script>
34 <script language="JavaScript">
35 secs = 59;
36 wait = secs * 100;
37 minute = 89; //此处设定考试总时间
38 //循环调用秒的减方法 cycle();
39 function cycle() {
40 for (i = 0; i <= (wait / 100); i++) {
41 //每隔一秒更新一次
42 window.setTimeout("doUpdate(" + i + ")", i * 1000);
43 }
44 }
45 function doUpdate(num) {
46 if (num == (wait / 100)) {
47 cycle();
48 //三分钟前提醒考生交卷
49 if (minute == 3) {
50 alert("还有三分钟时间,请及时交卷!");
51 }
52 //时间到,提交表单
53 if (minute <= 0) {
54 document.exam.action = "login.aspx";
55 document.exam.submit();
56 }
57 minute--;
58 }
59 else {
60 wut = (wait / 100) - num;
61 //使得输出格式为00:00
62 s = wut < 10 ? "0" + wut : wut;
63 m = minute < 10 ? "0" + minute : minute;
64 //将剩余时间显示在页面上
65 document.getElementById('lefttime').innerHTML = "剩余时间:" + m + "分" + s + "秒";
66 }
67 }
68 </script>
69 </head>
70 <body style="margin: 0px" scroll="no" onload="javascript:startclock(),cycle()">
71 <form id="form1" runat="server">
72 <table width="100%" height="100" border="0" cellspacing="0" cellpadding="0">
73 <tr>
74 <td height="58" valign="top">
75 <table width="100%" height="58" border="0" cellspacing="0" cellpadding="0" bgcolor="#4999ea">
76 <tr>
77 <td width="2%">
78 </td>
79 <td width="80%" height="58">
80 <div align="center">
81 <b><font color="white" size="5">考试系统计时及倒计时</font></b>
82 <br>
83 </div>
84 </td>
85 <td>
86 </td>
87 </tr>
88 </table>
89 </td>
90 </tr>
91 <tr>
92 <td>
93 <table width="100%" height="0" border="0" cellspacing="0" cellpadding="0">
94 <tr>
95 <td>
96 </td>
97 </tr>
98 <tr>
99 <td height="20" colspan="3" valign="middle" align="center" >
100 <table border="0" width="100%" valign="middle" height="30" align="center" bgcolor="#4999ea">
101 <tr align="left">
102 <td>
103 </td>
104 <td width="25%" align="right">
105
106 </td>
107 <td align="center" width="15%">
108 </td>
109 <td width="25%" align="left">
110 <span id="thetime" ></span>
111 </td>
112 <td width="20%" align="left">
113 <span id="lefttime" ></span>
114 </td>
115 <td width="5%">
116 </td>
117 </tr>
118 </table>
119 </td>
120 </tr>
121 </table>
122 </td>
123 </tr>
124 </table>
125 </form>
126 </body>
127 </html>
这种方法在做的时候,自己一开始是很认同的,因为最近接触了JavaScript DOM编程艺术,了解了很多DOM世界的内容,所以感觉这是一种很好的方法。可是事后一想才意识到这种方法真的不可取,存在很大的漏洞,不知道读者发现了没有。那下面我们一起来分析一下,这种方法到底存在什么问题:
当你把这段代码添加到你的页面的时候,一调试运行,你会很欣慰的看到页面上会显示当前时间,并按照你设定的考试时间倒计时,没错,这是大家都能看到的。那么现在请你刷新一下页面,请你告诉我发生了什么情况。没错,你看见了考试时间仍然在计时,但你再看看倒计时时间,是不是让人很沮丧,他是不是又重新开始倒计时了呀。对,没错,这就是问题的所在,也就是说在用这种方法实现倒计时,是基于客户端的,当用户进行页面刷新时,页面的JS会重新加载,那么倒计时会回到初始状态。这样一来就失去了所谓的倒计时功能,而且这种方法还有一种漏洞就是用户可以改掉本地机的时间,那么计时也会出现错误。
2.第二种方法:
我用的是AJAX来实现的
设计思想:在客户端界面上用AJAX的Timer控件,注意使用AJAX必须使用的另外两个AJAX控件也要一起使用。考试前由监考员做好所有相应的准备工作,考试开始由有监考员点击开始考试按钮,此时将开考状态值保存在Application中,这是一个全局变量值,且是一个公有变量,session是每个用户都有一个session,则无法实现共有变量的范围,相应的则考试结束时,监考员点击结束考试实现的是将Application中的状态值变为false,当监考员发布监考命令时,在服务器上,将开考时间保存在服务器的Application中。那么把客户端的Timer的属性设置为1000ms,则客户端每隔一秒到服务器去获取一次服务器的时间,这样得到一个时间差值,再利用考试时间来算考试所剩的时间,从而实现倒计时的模式。
编写的代码如下:
1 #region 计时器的实现
2 protected void Timer1_Tick(object sender, EventArgs e)
3 {
4 DateTime NowTime = System.DateTime.Now;
5 DateTime StartTime = Convert.ToDateTime(Application["StartTime"].ToString());
6 TimeSpan RemainTime = NowTime.Subtract(StartTime);
7 int hour = int.Parse(RemainTime.Hours.ToString());
8 int minute = int.Parse(RemainTime.Minutes.ToString());
9 int seconds = int.Parse(RemainTime.Seconds.ToString());
10 int time = 4;
11 string PaperInfo = Request.Cookies["PaperInfo"].Value;
12 if (hour >= 1)
13 {
14 time = (int.Parse(Request.Cookies[PaperInfo]["TotalTime"].ToString()) - 60 * hour - minute);
15 }
16 else
17 {
18 time = (int.Parse(Request.Cookies[PaperInfo]["TotalTime"].ToString()) - minute);
19 }
20 if (hour == 0 && time == 3 && seconds == 59)
21 {
22 Response.Write("<script language=javascript>alert('考试时间还剩下3分钟,请做好交卷准备!');</script>");
23 }
24 if (hour == 0 && time == 0 && seconds == 59)
25 {
26 Response.Write("<script language=javascript>alert('考试时间到,试卷将自动提交!');window.close();</script>");
27 }
28 this.LabelRemainingTime.Text = (time - 1).ToString() + "分钟" + (60 - seconds).ToString() + "秒";
29
30 }
31 #endregion
利用AjAx的Timer控件技术,那么相对于来说,是比较安全的一种做法,但这种方法会增大对服务器的请求量,会给服务器造成一定的压力。所以特定的方法也只能在特定的情况下适用,具体还是得看运行环境。