這是這篇系列的第三篇文章,實作的是對應模闆下題目及選項的增删。
一.資料庫表設計
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcugTMxgzN3MzNkVDN3UmZmRjY1YTMmRDMlVGOjBjZjdTMfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.png)
qsn資料表.PNG
detail表.PNG
一套模闆下可能有很多道題目,一對多關系,model_id對應模闆id,qsn_id為題目的主鍵,model_name對應模闆名稱,order_num對應模闆下題目的排序号,content對應題目的内容,qsn_type對應題目的類型,這裡有三種類型 type0為單選,type1為多選,type2為問答。
一道題也有可能對應很多選項,同理。這裡的option_num對應選項的内容,order_num對應選項的排序号
二.UI設計及功能設計
1.PNG
2.PNG
3.PNG
4.PNG
功能:當我們點選上面的資料表格1時,對複選框進行監聽顯示資料表格2,題目的資料表格,點選添加題目按鈕時,我們彈出選項框,填充題目内容,并且選擇題目類型且進行選項的增删。
三.代碼實作:
由于本篇專注于題目的增删,對資料表格1複選框的監聽,可以見layui官方文檔。
View層實作:
首先是對1.PNG中添加題目按鈕的點選
//彈出添加題目視窗
$('#btn-add').click(function() {
// alert(t_model_id);
layer.open({
type: 1,
skin: 'layui-layer-rim', //加上邊框
area: ['660px', '350px'], //寬高
content: $('#set-add-qsn'),
cancel: function(index, layero) {
$('#input_qus').empty();
layer.close(index)
k = 0;
$('#set-add-qsn input[name="content"]').val("");
$('#set-add-qsn div[name="input_qus"]').empty();
return false;
},
});
});
即彈出2.PNG的選項框(id為set-add-qsn的選項框)。
<!--添加題目彈出層-->
<div id="set-add-qsn" style="display:none; width:550px; padding:20px;">
<form class="layui-form" lay-filter="qsn_form">
<div class="layui-form-item">
<label class="layui-form-label">題目内容</label>
<div class="layui-input-block">
<input type="text" name="content" required lay-verify="required" placeholder="請輸入題目内容" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">請選擇問題的類型:</label>
<div class="layui-input-block">
<select name="qsn_type" lay-verify="required" style="width: 212px;">
<option value=""></option>
<option value="0">單選題</option>
<option value="1">多選題</option>
<option value="2">問答題</option>
</select>
</div>
<br/>
<div class="layui-input-block" id="input_qus" name="input_qus">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button type="button" class="layui-btn" id="add_op">添加選項</button>
<button type="button" class="layui-btn" id="del_op">減少選項</button>
<button type="button" class="layui-btn" lay-submit lay-filter="formDemo" id="commit">送出</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</div>
</form>
</div>
content代表題目内容,qsn_type下拉框代表題目類型,input_qus是根據qsn_type來顯示的添加按鈕,删除按鈕的域。
然後我們聲明一個letter數組,用來存放26個英文字母。并且聲明k,來記錄增加選項和删除選項的個數,并且對K值作為letter數組下标的索引
var k = 0;
var letter = new Array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z');
$('#add_op').click(function() {
$('#input_qus').append(
'<label class="layui-form-label" id="qs_letter" name="qs_letter">' + letter[k] + '</label>' + '<div class ="layui-input-block" id="qs_detail"><input type = "text" name = "user_op" lay-verify="required" placeholder = "請輸入選項' + (k + 1) + '" autocomplete = "off" class = "layui-input input_qs" id = "user_op' + k + '"></div>'
);
k++;
alert(k);
});
$('#del_op').click(function() {
$('#input_qus input[name="user_op"]:eq(' + (k - 1) + ')').remove(); //input_qs的第k個remove
$('#input_qus label[name="qs_letter"]:eq(' + (k - 1) + ')').remove(); //input_qs的第k個remove
$('#input_qus div[id="qs_detail"]:eq(' + (k - 1) + ')').remove();
if ($('#input_qus :eq(' + (k - 1) + ')' != null)) {
k--;
}
if ((k + 1) == 0) {
layer.msg("無法删減更多選項了");
$('#input_qus').empty();
k = 0;
}
alert(k);
});
這樣就能實作對單選(type=0)和多選問題(type=1)選項的增删。
form.on('select()', function(data) {
t_qsn_type = data.value;
// alert($('#set-add-qsn select[name="op_type"]').val());
if (data.value == 2) {
$('#add_op').attr('disabled', true);
$('#add_op').hide();
$('#del_op').attr('disabled', true);
$('#del_op').hide();
$('#input_qus').hide();
// form.render('select');
} else {
$('#add_op').attr('disabled', false);
$('#add_op').show();
$('#del_op').attr('disabled', false);
$('#del_op').show();
$('#input_qus').show();
}
});
同時對type=0,1以及type=2(問答題)進行不同按鈕功能的UI顯示,現在我們就能進行題目的增加啦。
題目選項.PNG
//确認送出問題到背景的按鈕
$('#commit').click(function() { //增加選項
var a = [];
$("#input_qus input[name='user_op']").each(function() { //往數組裡添加input裡擷取到的值
a.push($(this).val()); //往a數組裡添加
});
alert(a);
var content = $('input[name="content"]').val(); //擷取值
if (content !== '') {
//打開正在加載中彈出層
layer.msg('加載中', {
icon: 16,
shade: 0.01,
time: '9999999'
});
var qsn_type = t_qsn_type;
var model_id = t_model_id; //選擇到了模闆的id 然後随機生成一個qsnid 這個qsn的id下生成諸多問題選項
var model_name = t_model_name;
var url = 'manager/add_qsn';
var data = {
model_id: model_id, //模闆id用來生成qsn_id
content: content, //用來存儲問題内容
model_name: model_name,
a: a, //用來存儲所有問題的數組
qsn_type: qsn_type
}
$.post(url, data, function(data) { //确認送出
k = 0;
$('#set-add-qsn input[name="content"]').val("");
$('#set-add-qsn div[name="input_qus"]').empty();
layer.closeAll();
if (data.code == 1) {
layer.msg(data.msg, {
icon: 6
});
refresh_table1();
} else {
layer.msg(data.msg, {
icon: 5
});
}
}, "json ");
}
});
上傳五個參數,model_id和model_name對應題目的模闆表,content對應題目的内容,a用來對應所有選項的數組,qsn_type對應題目類型,我們接下來,将在背景進行qsn表的增加以及detail選項表的批量增加。
Controller層。
// modelId //模闆id用來生成qsnId
// content //用來存儲問題内容
// modelName
// a數組用來存儲所有問題
// qsn_type
//添加題目和選項
@RequestMapping(value="Index/manager/add_qsn")
@ResponseBody
public Map<String,Object> addQsnAndOption(HttpServletRequest req) throws IOException {
String modelId = req.getParameter("modelId");
String content=req.getParameter("content");
String modelName=req.getParameter("modelName");//有注解,預設轉換
String qsnType=req.getParameter("qsn_type");
String[] arr = req.getParameterValues("a[]");
UUID uuid=UUID.randomUUID();
String qsnId=uuid.toString();
UUID uuid1=UUID.randomUUID();
String flightId=uuid1.toString();
if (qsnType.equals(2)) {//問答題隻需要插入題目以及一條選項
//有題目了 根據modelId查出qsn的maxordernum
short orderNum = qsnService.findMaxOrderNum(modelId);
orderNum+=1;
Qsn qsn=new Qsn();
qsn.setOrderNum(orderNum);
qsn.setModelName(modelName);
qsn.setModelId(modelId);
qsn.setModelName(modelName);
qsn.setContent(content);
qsn.setQsnType(qsnType);
qsn.setQsnId(qsnId);
//查詢題目内容是否重複
Qsn isHasContent=qsnService.findByContent(content);
if (isHasContent==null){
short s1=0;
int isInsertQsn=qsnService.InsertQsn(qsn);
Detail detail=new Detail();
detail.setQsnId(qsnId);
detail.setOptionNum("0");
detail.setOrderNum(s1);
UUID uuid2=UUID.randomUUID();
String detailId=uuid2.toString();
detail.setDetailId(detailId);
int isInsertDetail=detailService.insertDetail(detail);
return api.returnJson(1,"添加成功");
}
}//否則單選多選還需要插入多條選項
short orderNum=0;
try {
orderNum = qsnService.findMaxOrderNum(modelId);
}catch(BindingException e){
e.printStackTrace();
}
orderNum+=1;
Qsn qsn=new Qsn();
qsn.setOrderNum(orderNum);
qsn.setModelName(modelName);
qsn.setModelId(modelId);
qsn.setModelName(modelName);
qsn.setContent(content);
qsn.setQsnType(qsnType);
qsn.setQsnId(qsnId);
//查詢題目内容是否重複
Qsn isHasContent=qsnService.findByContent(content);
if (isHasContent==null){
short s1=0;
int isInsertQsn=qsnService.InsertQsn(qsn);
for (int i = 0; i <arr.length ; i++) {
short j=(short)(i+1);
Detail detail=new Detail();
detail.setQsnId(qsnId);
detail.setType("0");
UUID uuid2=UUID.randomUUID();
String detailId=uuid2.toString();
detail.setDetailId(detailId);
detail.setOptionNum(arr[i]);
detail.setOrderNum(j);
int isInsertDetail=detailService.insertDetail(detail);
}
return api.returnJson(1,"添加成功");
}else {
return api.returnJson(3,"該問題已存在");
}
}
同樣對a數組進行字元串分割,然後進行題目表qsn的增加以及qsn_detail表的批量增加(通過對a數組長度的判别來進行批量增加次數的控制)
Service層:
qsnService:
package com.sl.example.service;
import com.sl.example.pojo.Model;
import com.sl.example.pojo.Qsn;
import java.util.List;
public interface QsnService {
public List<Qsn> findQsnList(String modelId);
public int deleteModel2Qsn(String modelId);
public short findMaxOrderNum(String modelId);
public Qsn findByOrderNum(short orderNum,String modelId);
public Qsn findByContent(String content);
public int InsertQsn(Qsn qsn);
public int deleteByQsnId(String qsnId);
}
qsnServiceImpl:
package com.sl.example.service;
import com.sl.example.dao.ModelMapper;
import com.sl.example.dao.QsnMapper;
import com.sl.example.pojo.Model;
import com.sl.example.pojo.Qsn;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
@Service("qsnService")
@Transactional
public class QsnServiceImpl implements QsnService{
@Resource
private QsnMapper qsnMapper;
@Override
public List<Qsn> findQsnList(String modelId) {
return qsnMapper.selectQsnList(modelId);
}
@Override
public int deleteModel2Qsn(String modelId) {
return qsnMapper.deleteByModelId(modelId);
}
@Override
public short findMaxOrderNum(String modelId) {
return qsnMapper.selectMaxOrderNum(modelId);
}
@Override
public Qsn findByOrderNum(short orderNum, String modelId) {
return qsnMapper.selectByOrderNum(orderNum,modelId);
}
@Override
public Qsn findByContent(String content) {
return qsnMapper.selectByContent(content);
}
@Override
public int InsertQsn(Qsn qsn) {
return qsnMapper.insertSelective(qsn);
}
@Override
public int deleteByQsnId(String qsnId) {
return qsnMapper.deleteByPrimaryKey(qsnId);
}
}
detailService:
package com.sl.example.service;
import com.sl.example.pojo.Detail;
import com.sl.example.pojo.Qsn;
import java.util.List;
public interface DetailService {
public List<Detail> findOptionList(String qsnId);
public Detail findAskAnswer(String qsnId);
public int insertDetail(Detail detail);
public int deleteOptionsByQsnId(String qsnId);
}
detailServiceImpl:
package com.sl.example.service;
import com.sl.example.dao.ChooseMapper;
import com.sl.example.dao.DetailMapper;
import com.sl.example.pojo.Detail;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
@Service("detailService")
@Transactional
public class DetailServiceImpl implements DetailService {
@Resource
private DetailMapper detailMapper;
@Override
public List<Detail> findOptionList(String qsnId) {
return detailMapper.selectOptionsByQsnId(qsnId);
}
@Override
public Detail findAskAnswer(String qsnId) {
return detailMapper.selectByQsnId(qsnId);
}
@Override
public int insertDetail(Detail detail) {
return detailMapper.insertSelective(detail);
}
@Override
public int deleteOptionsByQsnId(String qsnId) {
return detailMapper.deleteByQsnId(qsnId);
}
}
然後可以看見已經添加成功了。
add_qsn.PNG
然後我們對題目作删除。删除同樣跟删除模闆一樣,傳qsn_id數組到背景,删除的時候作級聯删除,删除qsn表中的題目 以及qsn_detail表中的選項,在此之前,判斷有沒有使用者作答過。
View層ajax實作:
$("#btn-delete-all").click(function() {
var model_id = t_model_id;
if (model_id) {
layer.confirm('您确定要删除這些資料嗎?', function(index) { //第二個參數為可選參數 點選确認以後的回調函數
layer.msg('加載中', {
icon: 16,
shade: 0.01,
time: '9999999'
});
var url = "manager/del_option";
var data = {
qsn_id: id_array //将目前選中行的qsn_id傳到後端
}
$.post(url, data, function(data) {
layer.close(layer.index); //關閉加載中彈窗
if (data.code == 1) {
layer.msg(data.msg, {
icon: 6
});
refresh_table1();
} else {
layer.msg(data.msg, {
icon: 5
});
}
}, "json"); //一定不要忘了這個json!!!
})
} else {
layer.msg("請先選擇模闆");
}
});
Controller層邏輯:
//qsnId數組
@RequestMapping(value="Index/manager/del_option")
@ResponseBody
public Map<String,Object> delOptions(HttpServletRequest req) throws IOException {
String[] arr = req.getParameterValues("qsnId[]");//前端傳來的modelId
//根據qsnId查詢出使用者選擇的答案
for (int i = 0; i < arr.length; i++) {
List<Choose> is_answer=chooseService.findByQsnId(arr[i]);
if (!is_answer.isEmpty()) {
return api.returnJson(3,"抱歉,題目已經被作答,無法删除");
}
continue;
}
//如果沒有 那麼目前選中模闆的題目都沒有被答過 作級聯删除 删除題目表 删除選項表(根據model查出Qsn 再根據qsnId删除Option)
for (int i = 0; i <arr.length ; i++) {
int is_del_qsn=qsnService.deleteByQsnId(arr[i]);//删除題目表
int isDelOptions=detailService.deleteOptionsByQsnId(arr[i]);
if (is_del_qsn!=0){
return api.returnJson(1,"删除成功");
}
}
return api.returnJson(2,"error");
}
四.效果展示
之前增加的題目資料已經顯示在資料表格了
然後我們删除題目。
1.gif
OK,完成啦