Vue之多选问卷设计
需求:智能中医项目需要在医院端设计一个填写多选的问卷模块,医生根据选项提示填写患者相关信息,用来存储中医中五脏六腑的信息。提交的问卷,可以在展示页面进行浏览,浏览已勾选的选项,不能进行修改。
设计:由el-checkbox
进行设计,还设计了单选和填空及问答,索性先全部设计,不过问卷只呈现了多选
提交格式:根据后端所需数据提交
部分效果图:
界面实现:
<el-dialog
title="五脏六腑问诊表"
:visible.sync="dialogQuestionnairePreview"
:close-on-click-modal="false"
>
<!--preview是从后端读来的数据存储-->
<div
v-for="(item, index) in preview"
:key="index"
style="margin-top: 30px"
>
<el-divider content-position="left">
<i class="el-icon-edit" />
题目{{ index+1 }}:{{ item.name }}
</el-divider>
<div
v-if="item.type=='单选'"
style="margin-top: 5px"
>
<el-radio
v-for="(option, index) in item.options"
:key="index"
v-model="item.content"
size="mini"
:label="option.id"
>
{{ option.name }}</el-radio>
</div>
<div
v-if="item.type=='多选'"
style="margin-top: 5px"
>
<el-checkbox-group
v-model="check"
size="mini"
@change="handleCheckChange"
>
<!--el-checkbox-width修改每行放多少个选项及选项字数过多换行-->
<el-checkbox
v-for="(option, index) in item.options"
:key="index"
class="el-checkbox-width"
:label="option.id"
:value="option.id"
@change="handleValuesChange(option)"
>
{{ option.name }}</el-checkbox>
</el-checkbox-group>
</div>
<div
v-if="item.type=='填空'"
style="margin-top: 5px"
>
<el-input
v-model="item.content"
type="textarea"
:rows="2"
placeholder="请输入内容" />
</div>
<div
v-if="item.type=='问答'"
style="margin-top: 5px"
>
<el-input
v-model="item.content"
type="textarea"
:rows="2"
placeholder="请输入内容" />
</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button
@click="dialogQuestionnairePreview =false"
>
取消</el-button>
<el-button
type="primary"
@click="handleSubmitQuestionnaire"
>
提交</el-button>
</div>
</el-dialog>
定义的data:
// 预览问卷
dialogQuestionnairePreview: false,
preview: [],
check: [], // 多选数据
values: [], // 多选id
temp: [], // 临时存储
// 提交问卷
final_answer: {
patientId: undefined,
answerList: []
},
// 提交问卷还需各种id
questionnaireId: undefined,
userId: undefined,
questionId: undefined
实现的功能:
// 预览问卷
handleQuestionnaire() {
// 打开问卷时置空
this.preview = []
this.check = []
this.values = []
this.temp = []
this.dialogQuestionnairePreview = true
// 固定了问卷id
fetchQuestionnaire(22).then(response => {
this.preview = response.data
})
},
// 下述用于检测
// 打印check数据,对应多选的label
handleCheckChange() {
// console.log("check",JSON.parse(JSON.stringify(this.check)))
},
// 打印value数据,对应多选的value
handleValuesChange(option) {
if (this.values.indexOf(option.id) === -1) {
this.values.push(option.id)
} else {
this.values.splice(this.values.indexOf(option.id), 1)
}
// console.log("value",JSON.parse(JSON.stringify(this.values)))
},
// 提交问卷
handleSubmitQuestionnaire() {
// 固定问卷的id
this.questionnaireId = 22
// 患者id,上一界面获取
this.patientId = this.$route.query.id
// 医生id,暂时固定,由后端直接覆盖
this.userId = 1
for (var i = 0; i < this.preview.length; i++) {
// 满足后端所需的格式
const p = {}
if (this.preview[i].type === '单选') {
// 单选内容返回id
p.content = this.preview[i].id
}
else if (this.preview[i].type === '多选') {
// 多选内容返回id,id,id ...
var contents = this.values // array
// 所选内容id在每一个题目下有对应id则把该id存储起来
for (var j = 0; j < this.preview[i].options.length; j++) {
for (var k = 0; k < contents.length; k++) {
if (contents[k] === this.preview[i].options[j].id) {
this.temp.push(this.preview[i].options[j].id)
}
}
p.content = this.temp.join(',')
}
this.temp = []
}
// 此处涉及的填空和问答方式一致,且为测试,只涉及思路
else if (this.preview[i].type === '填空') {
p.content = this.preview[i].content
}
else if (this.preview[i].type === '问答') {
p.content = this.preview[i].content
}
// 后端所需的数据,自行拼凑
p.questionnaireId = this.questionnaireId
p.patientId = this.patientId
p.userId = this.userId
p.questionId = this.preview[i].id
p.type = this.preview[i].type
this.final_answer.answerList[i] = p
this.final_answer.patientId = this.patientId
}
// 提交接口,final_answer存储最终要上交的数据,满足所需格式
submitQuestionnaire(this.final_answer).then(() => {
this.dialogQuestionnairePreview = false
this.$notify({
title: '成功',
message: '提交问卷成功',
type: 'success',
duration: 2000
})
})
// 测试一下数据和格式
// alert(JSON.stringify(this.final_answer))
}
浏览样式(注重多选处):
<el-dialog
title="五脏六腑问诊表"
:visible.sync="dialogQuestionnairePreview"
>
<div
v-for="(item, index) in preview"
:key="index"
style="margin-top: 30px">
<el-divider
content-position="left"
>
<i class="el-icon-edit" />
题目{{ index+1 }}:{{ item.question.name }}
</el-divider>
<div
v-if="item.type=='单选'"
style="margin-top: 5px"
>
<el-radio
v-for="(option, index) in item.question.options"
:key="index"
v-model="item.content"
size="mini"
:label="option.name"
>
{{ option.name }}</el-radio>
</div>
<!--selected === true 为选中-->
<div
v-if="item.type=='多选'"
style="margin-top: 5px">
<el-checkbox-group
v-model="check"
size="mini">
<!--onclick="return false" 无法选中修改,即为预览状态-->
<!--checked进行勾选判断,后端加字段即可-->
<el-checkbox
v-for="(option, index) in item.question.options"
:key="index"
class="el-checkbox-width"
onclick="return false"
:checked="option.selected == true"
:label="option.id"
>
{{ option.name }}</el-checkbox>
</el-checkbox-group>
</div>
<div
v-if="item.type=='填空'"
style="margin-top: 5px"
>
<el-input
v-model="item.question.options.content"
type="textarea"
:rows="2"
placeholder="请输入内容" />
</div>
<div
v-if="item.type=='问答'"
style="margin-top: 5px"
>
<el-input
v-model="item.question.options.content"
type="textarea"
:rows="2"
placeholder="请输入内容" />
</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogQuestionnairePreview =false">取消</el-button>
</div>
</el-dialog>
多选的样式(单选暂未测试):
<style>
.el-checkbox-width {
width: 200px;
height: auto;
margin-top: 10px;
}
.el-radio {
width: 200px;
margin-top: 10px;
}
.el-checkbox__label {
display: inline-grid;
padding-bottom: 2px;
white-space: pre-line;
word-wrap: break-word;
overflow: hidden;
line-height: 25px;
}
</style>
问卷系统的总结:
目前,通过与后端同学的沟通,独立完成平台端问卷系统的设计和医院端问卷填写与预览功能。
技术学习:熟练各种表格的增删改查,表单的验证和提交;掌握vue单选、多选组件的运用;掌握数据在不同界面的传递
其他学习:熟练Apifox的运用,熟练Git操作,规范代码书写格式(此处运用ESLint插件),规范页面布局(没有设计,只能根据RuoYi来参考进行设计)
未来学习:熟练各种业务逻辑、尝试组件化、尝试代码更加规范易读