Vue之多选问卷设计

需求:智能中医项目需要在医院端设计一个填写多选的问卷模块,医生根据选项提示填写患者相关信息,用来存储中医中五脏六腑的信息。提交的问卷,可以在展示页面进行浏览,浏览已勾选的选项,不能进行修改。

设计:由el-checkbox 进行设计,还设计了单选和填空及问答,索性先全部设计,不过问卷只呈现了多选

提交格式:根据后端所需数据提交

部分效果图:

image.png

界面实现:

<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来参考进行设计)

未来学习:熟练各种业务逻辑、尝试组件化、尝试代码更加规范易读

posted @ 2023-01-11 16:41  我在吃大西瓜呢  阅读(67)  评论(0编辑  收藏  举报