layui 实现问卷表单【页面数据渲染+答案提交】【前端完整代码】

最近有个业务需求,需要做一个问卷表单
格式比较简单:问题+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">&#xe666;</i>重置</button>
        <button type="submit" class="layui-btn" id="submit" lay-submit=""><i class="layui-icon">&#xe61f;</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}}.&nbsp;{{ 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}}&nbsp;&nbsp;{{ 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和所选答案),并要求不能有漏选问题,否则无法提交。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章