在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>