各位程序师大家好,上个月做了一个在线教育系统,其中有个考试系统模块,在这里有一些开发心得和大家分享。
我的代码结构是 数据库通过存储过程取出相对的数据,后台三层架构调用存储过程,前台Ajax无刷新展现数据,因为是做的手机端触屏版的网站所一分页了,其实也就是多了几个参数而已,不多说,直接上代码。
数据库:
存储过程
USE [itres]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE proc [dbo].[proc_getExampaperQuestion]
@pageIndex int,
@pagesize int,
@eId nvarchar(255), //试卷ID
@qtype nvarchar(20), //题型类别(单选多选填空)
@count int output
as
begin
declare @num int
select @count=count(*) from IT_Question where ExamId = @eId and QuestionType = @qtype
select * from (
select *,
len(replace(convert(varchar(max),RefAnswer),' ','')) as answer_len,
ROW_NUMBER() over(order by QuestionCode desc)as num
from IT_Question
where ExamID = @eId and QuestionType = @qtype)as t
where num between(@pageIndex-1)*@pagesize+1 and @pageIndex*@pagesize
end
这里可以根据自己的需求来修改。
三层中的
接口层
public intertface
{
DataTable GetQuestionByExamId(int pageIndex, int pagesize, string eId, string qtype, out int count);
}
DAL层
/// <summary>
/// 考试前 取出题目
/// </summary>
/// <param name="pageIndex"></param>
/// <param name="pagesize"></param>
/// <param name="eId"></param>
/// <param name="qtype"></param>
/// <param name="sid"></param>
/// <param name="count"></param>
/// <returns></returns>
public DataTable GetQuestionByExamId(int pageIndex, int pagesize, string eId, string qtype, out int count)
{
SqlParameter[] param = {
new SqlParameter("@pageIndex",SqlDbType.Int),
new SqlParameter("@pagesize",SqlDbType.Int),
new SqlParameter("@eId",SqlDbType.NVarChar,255),
new SqlParameter("@qtype",SqlDbType.NVarChar,20),
new SqlParameter("@count",SqlDbType.Int)
};
//设置输入参数
param[0].Value = pageIndex;
param[1].Value = pagesize;
param[2].Value = eId;
param[3].Value = qtype;
param[4].Direction = ParameterDirection.Output;
DataTable dt = DBResHelper.ExexProcQuery("proc_getExampaperQuestion", param);
int.TryParse(param[4].Value.ToString(), out count);
return dt;
}
BLL
//考试前
public DataTable GetQuestionByExamId(int pageIndex, int pagesize, string eId,string qtype,out int count)
{
return ie.GetQuestionByExamId(pageIndex, pagesize, eId, qtype,out count);
}
UI
Main.aspx
<body>
<form id="form1" runat="server">
<div>
<header id="examHeader" class="subtopic-head fixed-hd header" style="z-index:800;">
<a href="javascript:history.back();" class="back"><i></i></a>
<a href="javascript:;" class="time-pauses">
<i class="time">
<em class="num"><span class="static old">0</span></em>
<em class="num"><span class="static old">0</span></em>
<em><span>:</span></em>
<em class="num"><span class="static old">0</span></em>
<em class="num"><span class="static old">0</span></em>
<em><span>:</span></em>
<em class="num"><span class="static old">0</span></em>
<em class="num"><span class="static old">0</span></em>
</i>
</a>
<a href="javascript:;" class="pauses" id="tip"><i></i></a>
</header>
<div class="hd-occupy"></div>
<div id="examContainer" class='lyt-container foot-exam'>
<div class="lyt-question tk-subject" style=" height:4rem; border: 1px solid #dcdcdc; background:#f5f5f5;">
<input type="button" value="第一部分" style=" line-height:4rem; background:none; padding-left:20px; border:1px solid #f5f5f5;" onclick="showQusetion('panXz','panTk');" />
<input type="button" value="第二部分" style=" line-height:3rem; background:none;padding-left:30px; border:1px solid #f5f5f5;" onclick="showQusetion('panTk','panXz');" />
</div>
<div id="questionModule" class="lyt-question tk-subject">
<div id="panXz">
<ul>
<li >
<div class="m-question" style="height:600px;min-height:550px; max-height:1200px; ">
<dl class="tx-con">
<dt>
<em id="s_Index"></em><ems id="s_PrimQuestion"></ems>
<span id="s_QuestionCode" style=" display:none;"></span>
<span id="s_OrderCode" style=" display:none;"></span>
</dt>
<dd class="m-question-option" id="a_A" style="display:none;">
<a href="javascript:;">
<span>
<i id="clickme"><input type="radio" style=" display:none;" name="chioce" /></i>
</span>
<p>
<em id="ul_ChoiceA" style="display:none;width:0px;"></em>
<em>A.</em>
<em id="s_First"></em>
</p>
</a>
</dd>
<dd class="m-question-option" id="a_B" style="display:none;">
<a href="javascript:;">
<span>
<i><input type="radio" style=" display:none;" name="chioce"/></i>
</span>
<p>
<em id="ul_ChoiceB" style="display:none;width:0px;"></em>
<em>B.</em>
<em id="s_Second"></em>
</p>
</a>
</dd>
<dd class="m-question-option" id="a_C" style="display:none;">
<a href="javascript:;">
<span>
<i><input type="radio" style=" display:none;" name="chioce"/></i>
</span>
<p>
<em id="ul_ChoiceC" style="display:none;width:0px;"></em>
<em>C.</em>
<em id="s_Third"></em>
</p>
</a>
</dd>
<dd class="m-question-option" id="a_D" style="display:none;">
<a href="javascript:;">
<span>
<i><input type="radio" style=" display:none;" name="chioce"/></i>
</span>
<p>
<em id="ul_ChoiceD" style="display:none;"></em>
<em>D.</em>
<em id="s_Fourth"></em>
</p>
</a>
</dd>
<dd class="m-question-option" id="a_E" style="display:none;">
<a href="javascript:;">
<span>
<i><input type="radio" style=" display:none;" name="chioce"/></i>
</span>
<p>
<em id="ul_ChoiceE" style="display:none;"></em>
<em>E.</em>
<em id="s_Fifth" ></em>
</p>
</a>
</dd>
</dl>
</div>
</li>
</ul>
</div>
<!--简单题开始-->
<div id="panTk" style="display:none;">
<ul>
<li>
<div class="m-question" style="height:600px;min-height:550px; max-height:1200px; ">
<dl class="tx-con">
<dt>
<span id="w_QuestionCode" style=" display:none;"></span>
<span id="w_OrderCode" style=" display:none;"></span>
<em id="S_Indexs"></em>.<ems id="S_Qusetion"></ems>
</dt>
<dd id="w_questions">
<em style="display:block; height:4rem; line-height:4rem; font-size:1.4rem; border:1px solid #f0f0f0;">请在下方输入答案<i style="font-size:1.4rem; color:Red;"> (客观题请自行评分哦!)</i></em>
<span id="my-quest" style="width:100%; height:200px;"></span>
</dd>
</dl>
</div>
</li>
</ul>
</div>
<footer id="examFooter" class="footer tk-subfoot" style="z-index:400;">
<div class="submit-back" id="div_back">
</div>
<ul class="ft-menu" style="overflow:hidden;">
<li class="ks-paper">
<a id="submit_answer" >交卷</a>
</li>
</ul>
<div class="m-tlogin submit-btn" id="div_next">
</div>
</footer>
</div>
</div>
</div>
</form>
</body>
这里面包含了很多了,其中有分页,取出题目,答题,评分,交卷等都有,我一一注释一下。
Main.cs
private Content.CExam cce = new Content.CExam();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//Ajax方法
string action = Request[“action”];
switch (action)
{
case “GetExampaperQuestion”:
GetExampaperQuestion();
break;
case “AnswerBind”:
AnswerBind();
break;
}
}
}
//获取当前试卷下的所有试题
protected void GetExampaperQuestion()
{
string examId = Request["EId"];
int pageIndex = int.Parse(Request["pageIndex"]);
int pagesize = int.Parse(Request["pagesize"]);
string questtype = Request["qtype"];
int count = 0;
DataTable dt = cce.GetQuestionByExamId(pageIndex, pagesize, examId, questtype, out count);
var obj = new
{
count = count,
data = dt
};
string result = JsonConvert.SerializeObject(obj);
Response.Write(result);
Response.End();
}
//最重要的,前台获取答案以数组的形式传到后台
int Mysorce = 0;
private void AnswerBind()
{
string sq_arr_a = Request["sq_arr_a"];
DataTable dt = cce.GetAnswerByExamId(Request["EId"]);
List<Dictionary<string, string>> data = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(sq_arr_a);
Dictionary<string, string> all = new Dictionary<string, string>();
foreach (Dictionary<string, string> item in data)
{
if (!all.Keys.Contains(item["OrderCode"]))
{
all.Add(item["OrderCode"], item["answer"]);
}
else
{
all[item["OrderCode"]] = item["answer"];
}
}
for (int i = 0; i < dt.Rows.Count; i++)
{
string code = dt.Rows[i]["OrderCode"].ToString();
string strAnswer = dt.Rows[i]["RefAnswer"].ToString();
string Score = dt.Rows[i]["Score"].ToString();
if (all.Keys.Contains(code) && all[code] == strAnswer)
{
Mysorce += int.Parse(Score);
}
}
bool result = true;
string message = "";
int sid = SaveScore(Mysorce);
if (sid>0)
{
message = "已完成";
}
else
{
result = false;
message = "考试未完成";
}
var obj = new
{
complete = result,
msg = message,
Mysorce = Mysorce,
sid=sid
};
Response.Write(JsonConvert.SerializeObject(obj));
Response.End();
}
//保存得分
private int SaveScore(int myscore)
{
Content.CCollect cct = new Content.CCollect();
Content.CExam cce = new Content.CExam();
string uname = Session["UserName"].ToString();
DataTable dt = cct.GetIdByName(uname);
int uid = Convert.ToInt32(dt.Rows[0]["Id"].ToString());//用户id
string Eid = Request["Eid"]; //s试卷ID
DataTable de = cce.GetExamNameByExamId(Eid);
string examname = de.Rows[0]["ExamName"].ToString(); //试卷名称
DateTime ddy = System.DateTime.Now;
string MyAnswers = Request["answer_arr"];
int state = 1;
Modle.GradeModel mgg = new Modle.GradeModel();
mgg.ExamId = Eid;
mgg.EName = examname;
mgg.SaveTime = ddy;
mgg.status = state;
mgg.UserId = uid;
mgg.Score = myscore;
mgg.MyAnswer = MyAnswers;
int result = cce.SaveGrade(mgg);
return result;
}
[WebMethod]//收藏题目
public static string CollectQuest(string questionCode, string Myanswer, string ExamId)
{
if (HttpContext.Current.Session["UserName"] != null)
{
Content.CCollect ccc = new Content.CCollect();
string name = HttpContext.Current.Session["UserName"].ToString();
string youAnswer = Myanswer;
DataTable dt = ccc.GetIdByName(name);
int uid = Convert.ToInt32(dt.Rows[0]["Id"].ToString());//用户id
string qcode = questionCode;
string status = "显示";
string Eid = ExamId;
DateTime dtime = System.DateTime.Now;
Modle.MyQuestionModel myq = new Modle.MyQuestionModel();
myq.ExamId = Eid;
myq.AddTime = dtime;
myq.Status = status;
myq.UserId = uid;
myq.YouAnswer = youAnswer;
myq.QuestionCode = questionCode;
int flag = ccc.CollectQuestion(myq);
if (flag == 1)
{
return "1";
}
else
{
return "0";
}
}
else
{
return "2";
}
}
}
Main.aspx AJAX方法,前台方法
//这一块都来了,还有个考试倒计时的代码。
var Countdown = {
flag: true,
data: [0, 0, 0, 0, 0, 0],
init: function (hour, minute, second) {
var that = this;
if (that.flag) {
that.flag = false;
if (that.varliNum(hour) && that.varliNum(minute) && that.varliNum(second)) {
if (hour <= 0 && minute <= 0 && second <= 0) {
that.reset();
alert('考试时间已到');
return;
}
that.data[0] = parseInt(hour / 10);
that.data[1] = hour % 10;
that.data[2] = parseInt(minute / 10);
that.data[3] = minute % 10;
that.data[4] = parseInt(second / 10);
that.data[5] = second % 10;
$('.time').find("span.static:eq(0)").html(that.data[0]);
$('.time').find("span.static:eq(1)").html(that.data[1]);
$('.time').find("span.static:eq(2)").html(that.data[2]);
$('.time').find("span.static:eq(3)").html(that.data[3]);
$('.time').find("span.static:eq(4)").html(that.data[4]);
$('.time').find("span.static:eq(5)").html(that.data[5]);
that.begin();
} else {
alert('只能输入数字')
}
} else {
that.reset();
}
},
//数字校验
varliNum: function (value) {
return /^\d+$/.test(value)
},
reset: function () {
var that = this;
that.flag = true;
that.data = [0, 0, 0, 0, 0, 0];
},
//开始
begin: function () {
var that = this;
setTimeout(function () {
//判断是否为0
if (!that.flag) {
if (that.getData()) {
that.reset();
alert('时间到了。。。。')
} else {
that.begin();
}
}
}, 1000);
},
stop: function () {
clearTimeout(that);
},
//获取数据状态
getData: function () {
var that = this;
var data = that.data;
if (data[5] > 0) {
data = [data[0], data[1], data[2], data[3], data[4], data[5] - 1];
that.changeNum(5, data[5]);
} else if (data[4] > 0) {
data = [data[0], data[1], data[2], data[3], data[4] - 1, 9];
that.changeNum(4, data[4]);
that.changeNum(5, 9);
} else if (data[3] > 0) {
data = [data[0], data[1], data[2], data[3] - 1, 5, 9];
that.changeNum(3, data[3]);
that.changeNum(4, 5);
that.changeNum(5, 9);
} else if (data[2] > 0) {
data = [data[0], data[1], data[2] - 1, 9, 5, 9];
that.changeNum(2, data[2]);
that.changeNum(3, 9);
that.changeNum(4, 5);
that.changeNum(5, 9);
} else if (data[1] > 0) {
data = [data[0], data[1] - 1, 5, 9, 5, 9];
that.changeNum(1, data[1]);
that.changeNum(2, 5);
that.changeNum(3, 9);
that.changeNum(4, 5);
that.changeNum(5, 9);
} else if (data[0] > 0) {
data = [data[0] - 1, 9, 5, 9, 5, 9];
that.changeNum(0, data[0]);
that.changeNum(1, 9);
that.changeNum(2, 5);
that.changeNum(3, 9);
that.changeNum(4, 5);
that.changeNum(5, 9);
} else {
return true;
}
that.data = data;
return false;
},
//修改样式
changeNum: function (i, num) {
var that = this;
$('.time').find("span.old:eq(" + i + ")").before('<span class="static new">' + num + '</span>')
$(".old:eq(" + i + ")").animate({ top: "70px", opacity: '0' }, 300).remove();
$(".new").animate({ top: "0px", opacity: '1' }, 300).removeClass('new').addClass('old');
}
};
//也是JS插件实现的,这样一个完整的考试界面功能就实现了,大功告成,有什么问题,可以留言,必要的可以发送实例DEMO,