最近有個業務需求,需要做一個問卷表單
格式比較簡單:問題+radio選項,問題需要分組展示,數據需要從數據庫提取渲染。
細節較多
效果圖如下
下面發一下前端完整代碼(由於套用的是公司封裝的layui框架,layui的js請自己引入)
html+js
<body>
<div>
<h1 id="headline">大標題</h1>
<br/>
<div class="fr">
<button type="button" class="layui-btn" id="reset"><i class="layui-icon"></i>重置</button>
<button type="submit" class="layui-btn" id="submit" lay-submit=""><i class="layui-icon"></i>提交
</button>
</div>
<!-- 用了layui的tpl模板引擎-->
<div id="view"></div>
</div>
</body>
<script id="questionInfo" type="text/html">
<div class="layui-row">
<form class="layui-form">
<ul>
<!-- 對後臺傳過來的json數據進行遍歷-->
{{# layui.each(d.data, function(index, item){ }}
<!-- 問題分類(即二級標題)-->
<blockquote style=" text-align: left " class="layui-elem-quote"><span
style="font-size: 18px;font-weight: bold">{{index+1}}. {{ item.secondTitle}}</span>
</blockquote>
<!-- 遍歷每二級標題下對應的問題-->
<li class="layui-form-item" style=" text-align: left;margin-left: 20px">
{{# layui.each(item.list, function(key, value){ }}
<label style="font-size: 18px;font-weight: normal"> <span>{{index+1}}.{{key+1}} {{ value.question}} </span></label>
<!-- 問題提示功能,用了bootstrap的popover組件,若不需要可自行刪除-->
<button class="layui-btn " type="button" data-toggle="popover" data-container="body"
data-placement="right" data-content="{{value.notes}}" οnclick="hide()"
style=" height: 18px;line-height: 18px;padding: 0 8px;font-size: 10px">提示
</button>
<div class="checkList">
<!-- 根據我的客戶需求,需要在渲染頁面的時候,如果之前有過問卷提交記錄,則radio自動渲染出上次所選的選項-->
<input type="radio" name="{{ value.id}}" lay-verify="required" required
{{value.score=="1"?"checked":""}} value="1" title="準備實施"/>
<input type="radio" name="{{ value.id}}" lay-verify="required" required
{{value.score=="2"?"checked":""}} value="2" title="正在實施"/>
<input type="radio" name="{{ value.id}}" lay-verify="required" required
{{value.score=="3"?"checked":""}} value="3" title="已經實施"/>
</div>
{{# }); }}
</li>
{{# }); }}
</ul>
</form>
</div>
</script>
<script>
function hide() {//這個函數用來控制popover插件幾秒後消失,這裏是1500ms
setTimeout(function () {
$("[data-toggle='popover']").popover('hide');
}, 1500);
}
</script>
<script src="${ctxPath}/static/js/jquery-2.1.3.min.js"></script>
<script src="${ctxPath}/static/js/bootstrap.min.js"></script>
<script>
layui.use(['form', 'laytpl', 'layer'], function () {
var $ = layui.jquery
, form = layui.form
, layer = layui.layer
, laytpl = layui.laytpl;
form.render();
//把每項問題的Id和其所選值存入map
var map1 = new Map();
//map轉json(map -> object -> json)
function MapToJson(map) {
let obj = Object.create(null);
for (let [k, v] of map) {
obj[k] = v;
}
return obj;
}
var questionNumber = 0;
//獲取後臺數據
$.ajax({
url: "/tbQuestionRecord/getQuestion",
datatype: "json",
type: "GET",
async: false,//關閉異步,否則popover組件無法渲染出值
context: document.body,
success: function (data) {
for (var i in data.data) {
questionNumber += data.data[i].list.length;
}
var getTpl = questionInfo.innerHTML
, view = document.getElementById('view');
laytpl(getTpl).render(data, function (html) {
view.innerHTML = html;
});
form.render();
}
})
var TbQustionTechnologyInfo = {};
//按鈕操作
TbQustionTechnologyInfo.initButton = function () {
//提交信息
$("#submit").click(function () {
$.each($('.checkList').find('input'), function (i, n) {
$(n)
});
// 在提交之前需要遍歷一遍所有的radio選項,並把所選對應值存入map,如果有漏選的,則提交不成功
var dataList = $('.checkList').find('input');
for (var b = 0; b < dataList.length; b++) {
if ($(dataList[b]).prop('checked')) {
console.log($(dataList[b]).prop('checked'));
map1.set($(dataList[b])[0].name, $(dataList[b])[0].defaultValue);
}
}
if (questionNumber == map1.size) {
} else {
layer.msg("請填寫完所有選項");
return false;
}
$.ajax({
url:"/tbQuestionRecord/saveAnswer",
contentType:"application/json",
data:{
map: MapToJson(map1),
treeId: 1,
},
success:function (data) {
if (data.code == "200") {
alert(data.message);
} else if (data.code == "500") {
alert(data.message);
}
}
})
});
//重置
$("#reset").click(function () {
window.location.reload();
});
}
$(function () {
TbQustionTechnologyInfo.initButton(); //初始化按鈕操作
form.render();
$("[data-toggle='popover']").popover();
});
});
</script>
下面是前臺調用到的json數據格式
{
"data": [
{
"secondTitle": "問題分類第一組",
"list": [
{
//每個問題所屬於的二級菜單的Id(即secondTitle的Id)
"belongdemand": "2bf6a3191f5846629957d2974f879a9a",
//問題Id
"id": "19f26b2f364649c0958960870c5dcdb7",
//問題的備註
"notes": "1",
//問題
"question": "問題1.1",
//問題所得分數
"score": "1",
//問題的前後排序
"showorder": 5
},
{
"belongdemand": "2bf6a3191f5846629957d2974f879a9a",
"id": "840339d2c64044129553542fab9ceb4b",
"notes": "2",
"question": "問題1.2",
"score": "2",
"showorder": 7
},
{
"belongdemand": "2bf6a3191f5846629957d2974f879a9a",
"id": "6e31f891fb5745179897bd8b79b58ee7",
"notes": "4",
"question": "問題1.3",
"score": "2",
"showorder": 9
}
]
},
{
"secondTitle": "問題分類第二組",
"list": [
{
"belongdemand": "e55cb74dc159437ca35d47461f8efe02",
"id": "1143d2c1c3914f95b032c92dc27d84d9",
"notes": "達瓦大挖的",
"question": "問題2.1",
"score": "",
"showorder": 1
},
{
"belongdemand": "e55cb74dc159437ca35d47461f8efe02",
"id": "d22a6e1d6fbd4bf785b26715c315272f",
"notes": "達瓦打算達瓦w",
"question": "問題2.2",
"score": "",
"showorder": 2
}
]
}
]
}
由於業務需求不同,後端基本都是增刪改查,就不放代碼了。
如果遇到什麼問題或代碼有不對的地方,煩請指出和留言
開發過程中遇到的一些問題:
1.如何通過layui模板引擎循環遍歷顯示題目
2.如何在網頁加載後顯示上次提交的問題答案
3.如何在每次提交時拿到問題的所選答案,(我用的是map存放問題id和所選答案),並要求不能有漏選問題,否則無法提交。