VUE:问卷调查、答题类总结


在vue开发中问卷调查、答题类总结

说明

  • 服务端返回的数据,以及需要提交给服务端的数据
  • 具体思路
  • 主要代码

一、服务端返回的数据,以及需要提交给服务端的数据:

  • 服务端返回的数据:
//以下是服务端返回的试题列表数据
{
    "data": [
        {
            "id": 13,
            "type": 0,
            "title": "题目1?",
            "options": [
                {
                    "id": 1,// option_id
                    "question_id": 13,
                    "content": "选项1",
                    "score": 0,//分值
                    "ended": 0,// 是否结束题(0 否, 1 是)
                    "jump_id": null // 试题跳转id  注意:选项优先于试题进行跳转,如果都没有跳转id则进入下一题
                },
                {
                    "id": 2,
                    "question_id": 13,
                    "content": "选项2",
                    "score": 0,
                    "ended": 0,
                    "jump_id": 16
                },
                {
                    "id": 16,
                    "question_id": 13,
                    "content": "选项3",
                    "score": 0,
                    "ended": 0,
                    "jump_id": 16
                },
                {
                    "id": 22,
                    "question_id": 13,
                    "content": "选项4",
                    "score": 0,
                    "ended": 0,
                    "jump_id": null
                },
                {
                    "id": 23,
                    "question_id": 13,
                    "content": "选项5",
                    "score": 0,
                    "ended": 0,
                    "jump_id": null
                },
                {
                    "id": 25,
                    "question_id": 13,
                    "content": "选项6",
                    "score": 0,
                    "ended": 0,
                    "jump_id": null
                }
            ],
            "hint": null, // 提示信息
            "jump_id": null// 试题跳转id
        },
        {
            "id": 17,
            "type": 0,
            "title": "题目2",
            "options": [
                {
                    "id": 32,
                    "question_id": 17,
                    "content": "选项1",
                    "score": 0,
                    "ended": 0,
                    "jump_id": 18
                },
                {
                    "id": 33,
                    "question_id": 17,
                    "content": "选项2",
                    "score": 2.5,
                    "ended": 0,
                    "jump_id": 18
                },
                {
                    "id": 34,
                    "question_id": 17,
                    "content": "选项3",
                    "score": 3.5,
                    "ended": 0,
                    "jump_id": 18
                },
                {
                    "id": 35,
                    "question_id": 17,
                    "content": "选项4",
                    "score": 4.5,
                    "ended": 0,
                    "jump_id": 18
                }
            ],
            "hint": null,
            "jump_id": null
        },
  • 需要提交给服务端的数据:
  "data": {
    "list": [
      {
        "id": 17,
        "type": 1,
        "title": "题目1",
        "options": [
          {
            "id": 32,
            "question_id": 17,
            "content": "选项1",
            "score": 0,
            "ended": 0,
            "jump_id": 18,
            "select": 0
          },
          {
            "id": 33,
            "question_id": 17,
            "content": "选项2",
            "score": 2.5,
            "ended": 0,
            "jump_id": 18,
            "select": 0
          },
          {
            "id": 34,
            "question_id": 17,
            "content": "选项3",
            "score": 3.5,
            "ended": 0,
            "jump_id": 18,
            "select": 1
          },
          {
            "id": 35,
            "question_id": 17,
            "content": "选项4",
            "score": 4.5,
            "ended": 0,
            "jump_id": 18,
            "select": 1
          }
        ],
        "hint": null,
        "jump_id": null
      },
      {
        "id": 18,
        "type": 0,
        "title": "题目2",
        "options": [
          {
            "id": 36,
            "question_id": 18,
            "content": "选项1",
            "score": 0,
            "ended": 0,
            "jump_id": null,
            "select": 0
          },
          {
            "id": 37,
            "question_id": 18,
            "content": "选项2",
            "score": 1.76,
            "ended": 0,
            "jump_id": null,
            "select": 0
          },
          {
            "id": 38,
            "question_id": 18,
            "content": "选项3",
            "score": 5.27,
            "ended": 0,
            "jump_id": null,
            "select": 1
          },
          {
            "id": 39,
            "question_id": 18,
            "content": "选项4",
            "score": 2.64,
            "ended": 0,
            "jump_id": null,
            "select": 1
          }
        ],
        "hint": "题目注释",
        "jump_id": 17
      }
    ],
    "age": 21
  }

二、具体思路

1. 请求接口获取试题列表,并创建一个数组(list)用于最后的提交。

2. 判断第一题的类型(单、双选)并渲染。

3. 选择选项,在选中的选项中加入选中(select)属性。同时将该题(包含选项)添加进list。

4. 点击提交按钮,进行判断:

  • 判断是否选择了选项:是->继续判断;否->进行提示。
  • 判断选项中的ended(是否结束):0->继续判断;1->结束答题。
  • 判断选项中的jump_id(跳转题目):null->继续判断;!null->跳转到题目id为jump_id的题目。
  • 判断题目中的jump_id(跳转题目):null->跳转到当前题目索引的下一题; !null->跳转到题目id为jump_id的题目。

5. 结束答题时,将list进行提交

三、主要代码

<template>
  <div class="exposure-rating">
    <header class="top-title" style="color: #fff">
      <h5>风险评估</h5>
    </header>
    <div class="container">
      <div class="container-wrap">
        <!-- 题目  start  -->
        <div class="container-wrap-title">
          {{ SelectType[showTopic.type] }}
        </div>
        <div class="container-wrap-topic">
          {{ showTopic.title }}
          <span v-if="showTopic.hint">(*{{ showTopic.hint }})</span>
        </div>
        <!-- 题目  end    -->

        <!-- 单选模式渲染的试题选项  start  -->
        <van-radio-group
          v-model="radio"
          v-if="!showTopic.type"
          icon-size="17px"
          checked-color="#ffa135"
          class="container-wrap-elect"
        >
          <van-radio
            :name="index"
            v-for="(item, index) in showTopic.options"
            :key="index"
            @click="choice(item)"
            >{{ item.content }}
          </van-radio>
        </van-radio-group>
        <!-- 单选模式渲染的试题选项  end  -->

        <!-- 多选模式渲染的试题选项 start -->
        <van-checkbox-group
          v-model="result"
          :max="0"
          class="container-wrap-elect"
          icon-size="17px"
          checked-color="#ffa135"
          v-if="showTopic.type"
        >
          <van-checkbox
            :name="index"
            v-for="(item, index) in showTopic.options"
            :key="index"
            @click="choice(item)"
            >{{ item.content }}</van-checkbox
          >
        </van-checkbox-group>
        <!-- 多选模式渲染的试题选项 end -->
      </div>
    </div>

    <!-- 提交  start -->
    <footer>
      <van-button
        round
        type="info"
        class="submit"
        color="#6a74ef"
        @click="submit"
        :disabled="isdisabled"
        >下 一 题</van-button
      >
    </footer>
    <!-- 提交  end -->
  </div>
</template>

<script>
import { ApiModel } from "../../assets/js/request/api";
import { Toast } from "vant";
const apimodel = new ApiModel();
export default {
  data() {
    return {
      pullList: [], //请求获取的试题列表
      submitList: [], //最后提交需要的试题列表
      showTopic: {}, //渲染的试题
      index: 0, //题目索引
      radio: [], //单选
      result: [], //多选
      SelectType: {
        0: "单选",
        1: "多选",
      },
      jump_id: null, //选项跳转id
      ended: null, //是否结束答题
      isdisabled: false, //是否禁止答题
    };
  },
  mounted() {
    this.GetList(); //获取试题列表
  },
  methods: {
    // 1、获取试题列表
    GetList() {
      apimodel.getQuestionLists().then(
        (res) => {
          this.pullList = res.data.data; //获取到试题列表
          this.getTopic(); //渲染试题
        },
        (err) => {
          console.log(err, "错误原因");
        }
      );
    },
    // 2、渲染试题
    getTopic() {
      this.showTopic = this.pullList[this.index]; //获取渲染的试题
      this.result = []; //清空选项
      this.radio = [];
      console.log(
        "题目跳转id:",
        this.pullList[this.index].jump_id,
        "索引:",
        this.index
      );
    },
    // 3、选择选项
    choice(item) {
      /* 试题为单选 */
      if (this.showTopic.type == 0) {
        this.showTopic.options.map((item1) => {
          item1.select = 0;
        });
        item.select = 1;
        this.ended = item.ended; //是否结束答题
        this.jump_id = item.jump_id; //选项跳转id
        console.log(
          "(单选)",
          "是否结束答题:",
          this.ended,
          "选项跳转id:",
          this.jump_id
        );
        return;
      }
      /* 试题为多选 */
      if (this.showTopic.type == 1) {
        item.select = !item.select;
        if (item.select) {
          item.select = 1;
        } else {
          item.select = 0;
        }
        //过滤出有jump_id的选项
        let arry = this.showTopic.options.filter((item) => {
          return item.jump_id !== null;
        });
        //选项跳转id
        this.jump_id = arry[0].jump_id;
        //过滤出有ended的选项
        let arry1 = this.showTopic.options.filter((item) => {
          return item.ended !== null;
        });
        //是否结束答题
        this.ended = arry1[0].jump_id;
        console.log(
          "(多选)",
          "是否结束答题:",
          this.ended,
          "选项跳转id:",
          this.jump_id
        );
        return;
      }
    },
    // 4、提交
    submit() {
      let select = {
        isSingle: this.radio.length, //单选
        unSingle: this.result.length, //多选
        isEnd: this.ended, //是否结束答题
        jump_id: this.jump_id, //选项跳转id
        jumpId: this.showTopic.jump_id, //题目跳转id
        joinList: this.submitList.push(this.showTopic), //加入最后提交需要的试题列表
      };
      // 4.1、判断是否选择选项
      if (select.isSingle == 0 && select.unSingle == 0) {
        Toast.fail("请选择选项!");
        return;
      }
      // 4.2、判断是否结束答题
      if (select.isEnd) {
        select.joinList;
        this.getSubmit(); //提交
        return;
      }
      // 4.3、判断选项跳转id
      if (select.jump_id) {
        console.log("根据选项跳转");
        this.index = this.pullList.findIndex((item) => {
          return item.id == select.jump_id;
        });
        this.getTopic();
        return;
      }
      // 4.4、判断题目跳转id
      if (select.jumpId) {
        console.log("根据题目跳转");
        this.index = this.pullList.findIndex((item) => {
          return item.id == select.jumpId;
        });
        this.getTopic();
        return;
      }
      //4.5、根据题目索引跳转
      if (select.jump_id == null && select.jumpId == null) {
        console.log("根据题目索引跳转");
        let indexed = this.pullList.findIndex((item) => {
          return item.id == this.showTopic.id;
        });
        this.index = indexed + 1;
        this.getTopic();
        return;
      }
    },
    // 提交请求
    getSubmit() {
      this.isdisabled = true;
      let additional = JSON.parse(this.$route.query.additional);
      let data = {
        data: {
          list: this.submitList,
          additional: additional,
        },
      };
      apimodel.postAddRiskRecord(data).then(
        (res) => {
          let resultStatus = JSON.stringify(res.data.result_snapshot);
          window.sessionStorage.setItem("resultStatus", resultStatus);
          Toast.success("完成测试!");
          setTimeout(() => {
            this.$router.push({
              path: "/riskDetail",
              query: {
                fromRating: "1",
              },
            });
          }, 1500);
        },
        (err) => {
          console.log(err, "返回错误");
          Toast.fail(err.data.message);
        }
      );
    },
  },
};
</script>
<style lang="scss" scoped>
.exposure-rating {
  position: relative;
  background-image: linear-gradient(to right, #4a66da, #a2abe0);
  height: 100vh;
  .container {
    position: relative;
    width: 352px;
    height: 230px;
    margin: 20px auto 0;
    .container-wrap {
      position: absolute;
      z-index: 99;
      top: 10px;
      width: 322px;
      margin: 20px auto 0;
      padding: 10px 15px;
      border-radius: 10px;
      background-color: #fff;
      box-shadow: 0px 4px 14px 1px rgba(89, 103, 232, 0.12);
      .container-wrap-title {
        position: absolute;
        top: -7px;
        left: 15px;
        text-align: center;
        line-height: 36px;
        width: 36px;
        height: 36px;
        color: #fff;
        font-size: 13px;
        background-image: url("../../assets/img/risk-choice-bg.png");
        background-size: cover;
      }
      .container-wrap-topic {
        font-size: 20px;
        line-height: 28px;
        color: #222;
        margin-top: 46px;
        span {
          color: red;
          font-size: 12px;
          line-height: 12px;
        }
      }
      .container-wrap-elect {
        margin: 10px 0;
        font-size: 17px;
        div {
          margin: 20px 0 !important;
        }
      }
    }
  }
  footer {
    position: absolute;
    bottom: 0;
    background-color: #f2f3ff;
    height: 440px;
    width: 100%;
    .submit {
      position: fixed;
      bottom: 5%;
      width: 80%;
      left: 10%;
    }
  }
}
</style>


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM