我們之前三篇文章實作了模闆+題目+選項的增删,現在我們要完成答題管理系統的答題子產品啦。
一.UI及功能設計
既然是使用者答題,就要有一張表專門用來存放使用者答題的答案。我的設想是這樣的,我們點選答題按鈕的時候,就顯示出第一題,判斷是否是模闆下最後一題,來顯示名為next按鈕的字型樣式為下一題還是完成。并且,對背景傳過來的qsn_type進行區分,type=0的單選顯示單選框,type=1的多選顯示複選框,type=2的問答顯示文本域,大概是如下效果。
單選.PNG
多選.PNG
問答.PNG
為此,next按鈕要傳回的json格式資料如下。
建構json.PNG
用PHP構造一個二維關聯數組,其中二維數組中,還有一個二維數組,第一索引表示題目的order_num排序,第二索引表示option_num選項内容以及order_num選項排序号,最後将這個内層二維數組與别的參數使用PHP的array_merge函數進行數組合并,傳回給html頁面。
二.資料庫表設計(psg_qsn_r表)
image.png
主要的就是choose對應使用者選擇的選項,1,2,3...對應A,B,C,如果是問答,存的就是一串字元串。
三.代碼實作
首先是answer答題按鈕的點選監聽:
$('#btn-answer').click(function() {
// alert(id_array);
layer.msg('加載中', {
icon: 16,
shade: 0.01,
time: '9999999'
});
var url = "survey/answer_list";
var data = {
model_id: id_array //這裡将目前的model_id數組傳到後端
}
$.post(url, data, function(data) {
layer.close(layer.index); //關閉正在加載中彈出層
console.log(id_array);
if (data.code == 1) {
// alert(data.data[0].option_num);
if (data.data.bool_num == true) {
$('#next').text("完成");
}
$('#set-answer label[name="qsn_content1"]').css("width", "200px");
$('#set-answer label[name="qsn_content1"]').text(data.data.content);
if (data.data.qsn_type == 1) {
$.each(data.data, function(i, item) {
if (item.order_num == null) return false; //function中無法用break跳出 我們用return
//這邊要将type也傳過來 然後根據type來往anser_list中添加值
$('#answer_list').append(
// ' <br/><label class="layui-form-label">' + item.order_num + ':</label>' +
'<div class ="layui-input-block"><input type="checkbox" lay-skin="primary" name="checkbox[]" value="' + item.order_num + '" title="' + letter[item.order_num - 1] + ' : ' + item.option_num + '"></div>'
)
});
form.render('checkbox');
} else if (data.data.qsn_type == 0) {
$.each(data.data, function(i, item) {
if (item.order_num == null) return false; //function中無法用break跳出 我們用return
//這邊要将type也傳過來 然後根據type來往anser_list中添加值
$('#answer_list').append(
// ' <br/><label class="layui-form-label">' + item.order_num + ':</label>' +
'<div class ="layui-input-block"><input type="radio" lay-skin="primary" name="checkbox[]" value="' + item.order_num + '" title="' + letter[item.order_num - 1] + ' : ' + item.option_num + '"></div>'
)
});
form.render('radio');
} else if (data.data.qsn_type == 2) {
// if (item.order_num == null) return false; //function中無法用break跳出 我們用return
//這邊要将type也傳過來 然後根據type來往anser_list中添加值
$('#answer_list').append(
// ' <br/><label class="layui-form-label">' + item.order_num + ':</label>' +
' <div class ="layui-input-block"><textarea name="text" id="text" required lay-verify="required" placeholder="請輸入" class="layui-textarea"></textarea>'
)
form.render();
}
// alert(data.data.order_num);
getqsn_type(data.data.qsn_type);
getmodel_id(data.data.model_id);
getorder_num(data.data.order_num);
layer.open({
type: 1,
skin: 'layui-layer-rim', //加上邊框
area: ['660px', '350px'], //寬高
content: $('#set-answer'),
cancel: function(index, layero) {
$('#answer_list').empty();
$('#next').text("下一題");
layer.close(index)
return false;
},
end: function() {
$('#answer_list').empty();
$('#next').text("下一題");
layer.closeAll();
}
});
} else {
layer.msg(data.msg, {
icon: 5
});
}
}, "json");
});
其中有對問題類型進行判别,并且對next樣式作更改,然後是其對應的Controller層:
@RequestMapping(value="Index/survey/answer_list")
@ResponseBody
public Map<String,Object> firstAnswer(HttpServletRequest req) throws IOException{
String[] arr_modelId = req.getParameterValues("modelId[]");
Map map=new HashMap();
if (arr_modelId.length==0)
return api.returnJson(3,"請選擇模闆答題");
String modelId=arr_modelId[0];
List<Qsn> qsnList=qsnService.findQsnList(modelId);
if (qsnList.isEmpty()){
return api.returnJson(2,"暫無題目");
}
boolean bool_num=false;
//判斷這套模闆的第一道題目是否是最後一題
if(qsnList.get(0).getOrderNum()==qsnService.findMaxOrderNum(modelId))
bool_num=true;
//不管是不是最後一題,都查詢選項
List<Detail> optionList=detailService.findOptionList(qsnList.get(0).getQsnId());
if (!qsnList.get(0).getQsnType().equals(2)){//單選/多選
map.put("qsn_type",qsnList.get(0).getQsnType());
map.put("content",qsnList.get(0).getContent());
map.put("modelId",qsnList.get(0).getModelId());
map.put("orderNum",qsnList.get(0).getOrderNum());
map.put("qsnId",qsnList.get(0).getQsnId());
map.put("bool_num",bool_num);
for (int i = 0; i <optionList.size() ; i++) {
map.put(i,optionList.get(i));
}
return api.returnJson(1,"success",map);
}else{//問答題
map.put("qsn_type",qsnList.get(0).getQsnType());
map.put("content",qsnList.get(0).getContent());
map.put("modelId",qsnList.get(0).getModelId());
map.put("orderNum",qsnList.get(0).getOrderNum());
map.put("qsnId",qsnList.get(0).getQsnId());
map.put("bool_num",bool_num);
for (int i = 0; i <optionList.size() ; i++) {
map.put(i,optionList.get(i));
}
return api.returnJson(1,"success",map);
// return api.returnJson(2,"此路不通");
}
}
然後是View層next按鈕的監聽事件,跟這個差不多。
$('#next').click(function() {
var qsn_type = t_qsn_type;
var is_answered = false;
if (qsn_type == 1) {
var count = $("#set-answer input[type='checkbox']:checked").length
if (count == 0) {
is_answered = true;
}
$("#set-answer input[type='checkbox']:checked").each(function() {
choice.push($(this).val());
});
} else if (qsn_type == 0) {
var count = $("#set-answer input[type='radio']:checked").length
if (count == 0) {
is_answered = true;
}
$("#set-answer input[type='radio']:checked").each(function() {
choice.push($(this).val());
});
} else if (qsn_type == 2) {
var count = $("#set-answer #text").length
if (count == 0) {
is_answered = true;
}
$("#set-answer #text").each(function() {
choice.push($(this).val());
});
}
if (is_answered == true) {
layer.msg('請選擇答案');
return;
}
alert(choice);
layer.msg('加載中', {
icon: 16,
shade: 0.01,
time: '9999999'
});
alert(choice);
var url = "survey/next_qsn";
var t_choice = choice;
var model_id = t_model_id;
var order_num = t_order_num;
var data = {
model_id: model_id,
order_num: order_num,
choice: t_choice,
qsn_type: qsn_type
}
$.post(url, data, function(data) {
layer.close(layer.index); //關閉正在加載中彈出層
form.render(null, 'answer');
choice = [];
console.log(id_array);
if (data.code == 1) {
if (data.data.bool_num == true) {
$('#next').text("完成");
}
// alert(data.data[0].option_num);
$('#answer_list').empty();
$('#set-answer label[name="qsn_content1"]').text(data.data.content);
// alert(data.data.order_num);
if (data.data.qsn_type == 1) {
$.each(data.data, function(i, item) {
if (item.order_num == null) return false; //function中無法用break跳出 我們用return
$('#answer_list').append(
// ' <br/><label class="layui-form-label">' + item.order_num + ':</label>' +
'<div class ="layui-input-block"><input type="checkbox" lay-skin="primary" name="sex" value="' + item.order_num + '" title="' + letter[item.order_num - 1] + ' : ' + item.option_num + '"></div>'
)
});
form.render('checkbox');
} else if (data.data.qsn_type == 0) {
$.each(data.data, function(i, item) {
if (item.order_num == null) return false; //function中無法用break跳出 我們用return
//這邊要将type也傳過來 然後根據type來往anser_list中添加值
$('#answer_list').append(
// ' <br/><label class="layui-form-label">' + item.order_num + ':</label>' +
'<div class ="layui-input-block"><input type="radio" lay-skin="primary" name="checkbox[]" value="' + item.order_num + '" title="' + letter[item.order_num - 1] + ' : ' + item.option_num + '"></div>'
)
});
form.render('radio');
} else if (data.data.qsn_type == 2) {
$('#answer_list').append(
// ' <br/><label class="layui-form-label">' + item.order_num + ':</label>' +
' <div class ="layui-input-block"><textarea name="text" id="text" lay-verify="required" placeholder="請輸入" class="layui-textarea"></textarea>'
)
form.render();
}
getqsn_type(data.data.qsn_type);
getmodel_id(data.data.model_id);
getorder_num(data.data.order_num);
} else if (data.code == 2) {
layer.msg(data.msg, {
icon: 6
});
setTimeout('layer.closeAll()', 2000);
} else if (data.code == 3) {
layer.msg(data.msg, {
icon: 5
});
}
}, "json");
然後是Controller層代碼。
//下一題 這題答題錄入 并傳回下一題資料
// modelId
// orderNum
// choice//數組
// qsn_type
@RequestMapping(value="Index/survey/next_qsn")
@ResponseBody
public Map<String,Object> answerRecord(HttpServletRequest req) throws IOException{
String modelId = req.getParameter("modelId");
String str_orderNum = req.getParameter("orderNum");
String qsnType = req.getParameter("qsn_type");
String[] choose = req.getParameterValues("array[]");
Map map=new HashMap();
short orderNum=Short.parseShort(str_orderNum);
if(choose.length==0)
return api.returnJson(3,"請答題");
Qsn qsn=qsnService.findByOrderNum(orderNum,modelId);
Choose c=new Choose();
c.setQsnId(qsn.getQsnId());
c.setModelId(qsn.getModelId());
c.setFlightId(qsn.getFlightId());
c.setQsnType(qsn.getQsnType());
if (!qsnType.equals(2)) {
String str_choose = StringUtils.join(choose, ",");
List<Detail> optionList = detailService.findOptionList(qsn.getQsnId());
for (int i = 0; i < choose.length; i++) {
c.setDetailId(optionList.get(i).getDetailId());
c.setChoose(choose[i]);
UUID uuid = UUID.randomUUID();
String psgQsnId = uuid.toString();
c.setPsgQsnRId(psgQsnId);
int isInsert = chooseService.InsertChoose(c);
}
}else{//如果是2的話 那就是整個錄入進去
String str_choose=choose[0];
List<Detail> optionList = detailService.findOptionList(qsn.getQsnId());
c.setDetailId(optionList.get(0).getDetailId());
c.setChoose(str_choose);
UUID uuid = UUID.randomUUID();
String psgQsnId = uuid.toString();
c.setPsgQsnRId(psgQsnId);
int isInsert = chooseService.InsertChoose(c);
}
//然後我們要傳回下一題的資料 這裡注意orderNum+=1和orderNum=orderNum+1
short s=1;
orderNum=(short) (orderNum+s);
Qsn qsnNext=qsnService.findByOrderNum(orderNum,modelId);
boolean bool_num=false;
if (qsnNext==null){
return api.returnJson(2,"恭喜您完成了答題");
}
if (qsnNext.getOrderNum()==qsnService.findMaxOrderNum(modelId)){
bool_num=true;
}
//然後我們查詢選項
List<Detail> optionList1=detailService.findOptionList(qsnNext.getQsnId());
if (!qsnNext.getQsnType().equals(2)){//單選/多選
map.put("qsn_type",qsnNext.getQsnType());
map.put("content",qsnNext.getContent());
map.put("modelId",qsnNext.getModelId());
map.put("orderNum",qsnNext.getOrderNum());
map.put("qsnId",qsnNext.getQsnId());
map.put("bool_num",bool_num);
for (int i = 0; i <optionList1.size() ; i++) {
map.put(i,optionList1.get(i));
}
return api.returnJson(1,"success",map);
}else {//問答題
map.put("qsn_type", qsnNext.getQsnType());
map.put("content", qsnNext.getContent());
map.put("modelId", qsnNext.getModelId());
map.put("orderNum", qsnNext.getOrderNum());
map.put("qsnId", qsnNext.getQsnId());
map.put("bool_num", bool_num);
for (int i = 0; i < optionList1.size(); i++) {
map.put(i, optionList1.get(i));
}
return api.returnJson(1, "success", map);
}
}
除了上一節提供的qsn和detail的Service層代碼 這裡還需要chooseService的代碼:
chooseService:
package com.sl.example.service;
import com.sl.example.pojo.Choose;
import java.util.List;
public interface ChooseService {
public List<Choose> findChooseByModelId(String modelId);
List<Choose> countDataBy2Id(String qsnId,String detailId);
public int InsertChoose(Choose record);
List<Choose> findByQsnId(String qsnId);
}
chooseServiceImpl:
package com.sl.example.service;
import com.sl.example.dao.ChooseMapper;
import com.sl.example.dao.ModelMapper;
import com.sl.example.pojo.Choose;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
@Service("chooseService")
@Transactional
public class ChooseServiceImpl implements ChooseService{
@Resource
private ChooseMapper chooseMapper;
@Override
public List<Choose> findChooseByModelId(String modelId) {
return chooseMapper.selectByModelId(modelId);
}
@Override
public List<Choose> countDataBy2Id(String qsnId, String detailId) {
return chooseMapper.selectByQsnIdDetailId(qsnId,detailId);
}
@Override
public int InsertChoose(Choose record) {
return chooseMapper.insertSelective(record);
}
@Override
public List<Choose> findByQsnId(String qsnId) {
return chooseMapper.selectByQsnId(qsnId);
}
}
然後我們看看最終的效果。
四.效果一覽
1.gif
OK,完成啦