最近有个业务需求,需要做一个问卷表单
格式比较简单:问题+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}}" onclick="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 () {
// 在提交之前需要遍历一遍所有的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和所选答案),并要求不能有漏选问题,否则无法提交。