需求:问卷调查
1.返回的数据中包含单选、多选、多项文本框、单文本框、图片上传
2.需要对必填的选项进行校验
3.非必填的多项文本框内容 如果不填写 不提交
javascript
表单数据格式
res={
"code": 0,
"msg": null,
"data": [
{
"executeDay": "2023-12-18",
"infoList": [ //表单数据
{
"id": "",
"recordId": "",
"taskId": "",
"itemId": "",
"itemName": "",
"subtype": 1,//根据这个数值区分 表单的类型 1单选 2多选 3多填空 4 文本框 5上传文件 6基本信息
"executeDate": "",
"states": "0",// 是否为必填项目 0表示必填 1表示非必填
"times": 1,
"timing": "8:00",
"executeTimes": 0,
"delFlag": "0",
"content": "{}",
"executeDay": "2023-12-18"
}
]
}
]
}
javascript
<view class="reportData" v-for="(val, index) in obj" :key="index">
<view class="reportData-title"><text class='red'
v-if='val.requiredFlag==0'>*</text>{{index+1+'.'}}{{ val.questionContent }}</view>
<view v-if="val.questionType ==1" class="chbox">
<u-radio-group v-model="submitData[index].optionValue" placement="column"
@change="(e)=>groupChange(e, val)" :key="index">
<block v-for="(item, i) in val.optionInfoList">
<!-- 其它选项 -->
<view v-if="item.optionType=='1'" style="display:flex" >
<u-radio :customStyle="{marginBottom: '20rpx'}" :label="item.optionName"
:name="item.optionName" @change="e=>radioChange(e,item,index)">
</u-radio>
<u--input placeholder="其他-具体描述" v-model="submitData[index].remark" class="cc_input"
style="height:24rpx;font-size: 30rpx;margin-left:20rpx ;" v-if="submitData[index].optionValue.indexOf('其他')!= -1"
></u--input>
</view>
<u-radio :customStyle="{marginBottom: '20rpx'}" v-else :label="item.optionName"
:name="item.optionName" @change="e=>radioChange(e,item,index)">
</u-radio>
</block>
</u-radio-group>
</view>
<!-- 多选 -->
<view v-if="val.questionType ==2" class="chbox">
<u-checkbox-group v-model="submitData[index].optionValue" placement="column"
@change="(e) =>checkboxChange(e, val)">
<block v-for="(item, i) in val.optionInfoList" :key="index" >
<view v-if="item.optionType=='1'" style="display:flex" >
<u-checkbox :customStyle="{marginBottom: '20rpx'}"
:label="item.optionName" :name="item.optionName">
</u-checkbox>
<u--input placeholder="其他具体描述" v-model="submitData[index].remark" class="cc_input"
style="height:24rpx;font-size: 30rpx;margin-left:20rpx ;" v-if="submitData[index].optionValue.indexOf('其他')!= -1"
></u--input>
</view>
<u-checkbox :customStyle="{marginBottom: '20rpx'}" v-else :label="item.optionName" :name="item.optionName">
</u-checkbox>
</block>
</u-checkbox-group>
</view>
<!-- 文本上传 -->
<view v-else-if="val.questionType ==4" class="chbox">
<up-load @afterRead='val=>afterRead(val,index)' @deletePic='val=>deletePic(val,index)'></up-load>
</view>
<!-- 文本框-->
<view v-else-if="val.questionType ==5" class="chbox">
<textarea class="investigate-propose" placeholder="请输入" v-model="submitData[index].optionValue"
name="propose" id="" cols="30" rows="10"></textarea>
</view>
<!-- 6.个人的基本信息 -->
<view v-if="val.questionType ==6 || val.questionType ==3" class="chbox">
<view class="item" v-for="(item,i) in submitData[index].info">
<view class="name">{{item.optionTitle}}:</view>
<!-- 数值 -->
<view class="c_name" v-if="item.optionType==2">
<u--input placeholder="请输入数值" type='number' v-model="item.cname"
class="cc_input"></u--input>
</view>
<!-- 时间 -->
<view class="c_name" @click="item.showState = true" v-else-if="item.optionType==3">
<u--input placeholder="请输入时间" v-model="item.cname" class="cc_input"></u--input>
<u-calendar :closeOnClickOverlay='true' :show="item.showState"
@confirm="e=>confirm(e,i,index)" @close='item.showState = false'>
</u-calendar>
</view>
<!-- 文本 -->
<view class="c_name" v-else>
<u--input placeholder="请输入数值" type='number' v-model="item.cname"
class="cc_input"></u--input>
</view>
</view>
</view>
<script>
<script>
import http from '@/untils/http'//请求接口的封装
import upLoad from '@/pages/components/upLoad.vue'//图片上传的封装
export default {
components: {
upLoad
},
data() {
return {
id:"",
formData: {
itemId: '',
subtype: ''
},
obj: {},
infoList: '',
subtype: '',
submitData: [], // submitData[{info:[{item:1}]}]
optionsObj: { //需要提交给后台的数据
"userId": '',
"taskId": '', //问卷的id taskId"1736623815192743937"
"taskNmae": "",
"surveyId": "1", // itemId
"surveyName": "", //
"totalScore": "",
"taskInfoId": "12", // id
}
}
},
onLoad(options) {
this.optionsObj = {
"userId": this.$store.state.userInfo.userId,
"taskId": options.taskId, //问卷的id taskId"1736623815192743937"
"taskNmae": "",
"surveyId": options.itemId, // itemId
"surveyName": options.surveyName, //
"totalScore": "",
"taskInfoId": options.id, // id
}
this.initData()
},
methods: {
// 回显数据
async showData(){
let {data}=await http.savefindByTaskInfoId(this.id)
console.log(res)
this.obj=data.infoList
},
// 时间下拉框 确认按钮
confirm(e, i, index) {
this.obj[index].info[i].cname = e.toString()
this.obj[index].info[i].showState = false
},
// 提交按钮
submitFn() {
let sendFrom = JSON.parse(JSON.stringify(this.submitData))
sendFrom = sendFrom.map((item, index) => {
// 将字符串转化为数组
if (typeof(item.optionValue) == 'string') {
item.optionValue = item.optionValue.length == 0 ? [] : item.optionValue.split();
}
if (item.info && item.info.length > 0) {
// 过滤掉 空的数组
for (let i = 0; i < item.info.length; i++) {
if (item.info[i].cname != '') {
item.optionValue.push(item.info[i].cname)
item.optionTitle.push(item.info[i].optionTitle)
}
}
}
return item
})
// 校验部分 是否需要必填
for (let i = 0; i < sendFrom.length; i++) {
if (sendFrom[i].requiredFlag == 0) {
if (sendFrom[i].optionValue.length == 0) {
this.$refs.uToast.show({
message: `第${i+1}题未填写`
});
break
}
if (sendFrom[i].optionValue.indexOf('') != -1) {
this.$refs.uToast.show({
message: `第${i+1}题未填写`
});
break
}
}
}
// console.log(sendFrom)
this.sendFrom(sendFrom)
},
async sendFrom(val) {
let sendFrom = {
...this.optionsObj,
"infoList": val
}
let {
data,
code,
msg
} = await http.saveUserQuestionnaire(sendFrom)
if (code == 0) {
this.$refs.uToast.show({
message: data
})
uni.navigateTo({
url: '/pages/Option/sucess/sucess'
})
} else {
this.$refs.uToast.show({
message: msg
})
}
},
// afterRead 上传图片
afterRead(val, index) {
this.submitData[index].optionValue = val.map(item => {
return item.url.filePath
})
},
// 删除图片
deletePic(val, index) {
this.submitData[index].optionValue = []
this.submitData[index].optionValue = val
},
// 单选框按钮处理
groupChange(e, val) {
console.log(e,val,'dyd')
this.submitData = this.submitData.map(item => {
if (val.id == item.itemId) {
item.optionValue = e
}
return item
})
},
// 复选框
checkboxChange(e, val) {
this.submitData = this.submitData.map(item => {
if (val.id == item.itemId) {
item.optionValue = e
}
return item
})
},
async initData() {
let res = await http.getFindByInfo(this.formData)
this.obj = res.data.questionInfoList.map(item => {
if (item.questionType == 2 || item.questionType == 4) {
this.submitData.push({
itemId: item.id, //题目的id
optionValue: [],
fraction: item.fraction,
questionNumber: item.questionNumber,
questionContent: item.questionContent, //问题
requiredFlag: item.requiredFlag,
questionId: item.questionId,
optionTitle: item.optionTitle,
remark:'',
questionType:item.questionType
})
// 基本信息部分
} else if (item.questionType == 6 || item.questionType == 3) {
this.submitData.push({
itemId: item.id, //题目的id
optionValue: [],
info: [],
fraction: item.fraction,
questionNumber: item.questionNumber,
questionContent: item.questionContent, //问题
requiredFlag: item.requiredFlag,
questionId: item.questionId,
optionTitle: [],
remark:'',
questionType:item.questionType
})
item.optionInfoList.map(item2 => {
this.submitData = this.submitData.map(item3 => {
if (item.id == item3.itemId) {
let cname = 'cid' + item2.id
item3.info.push({
id: item2.id,
cname: '',
fraction: item2.fraction,
optionTitle: item2.optionTitle,
showState: false, //是否可以打开时间的下拉框
})
}
return item3
})
})
} else {
this.submitData.push({
itemId: item.id, //题目的id
optionValue: '',
fraction: item.fraction,
questionNumber: item.questionNumber,
questionContent: item.questionContent, //问题
requiredFlag: item.requiredFlag,
questionId: item.questionId,
optionTitle: item.optionTitle,
questionType:item.questionType
})
}
item.optionInfoList.map(item2 => {
item2.disabled = false
})
return item
})
},
// 单选按钮切换
radioChange(e, item,index) {
if(e=='其他') {
}else {
this.submitData[index].remark=''
}
},
}
}
</script>
//对uviews上传组件进行了二次封装
javascript
<template>
<u-upload :fileList="fileList6" @afterRead="afterRead" @delete="deletePic" name="6" multiple :maxCount="10"
:width="wWidth" :height="hHeight" >
</u-upload>
</template>
<script>
export default {
props: {
wWidth:{ //图片的宽度
type: Number,
default: 58,
},
hHeight:{// 图片的高度
type: Number,
default: 58,
},
},
data() {
return {
fileList6: [],
}
},
methods: {
// 添加图片时间
async afterRead(event) {
// 当设置 multiple 为 true 时, file 为数组格式,否则为对象格式
let lists = [].concat(event.file)
let fileListLen = this[`fileList${event.name}`].length
lists.map((item) => {
this[`fileList${event.name}`].push({
...item,
status: 'uploading',
message: '上传中'
})
})
for (let i = 0; i < lists.length; i++) {
const result = await this.uploadFilePromise(lists[i].url)
let item = this[`fileList${event.name}`][fileListLen]
this[`fileList${event.name}`].splice(fileListLen, 1, Object.assign(item, {
status: 'success',
message: '',
url: result
}))
fileListLen++
}
this.$emit('afterRead',this.fileList6)
},
uploadFilePromise(url) {
return new Promise((resolve, reject) => {
let a = uni.uploadFile({
url: '/sapi/file/uploadImageMobile', // 仅为示例,非真实的接口地址
filePath: url,
name: 'file',
formData: {
bizType: "patient",
},
success: (res) => {
setTimeout(() => {
let data=JSON.parse(res.data)
resolve(data.data)
}, 1000)
}
});
})
},
// 删除图片
deletePic(event) {
this[`fileList${event.name}`].splice(event.index, 1);
this.$emit('deletePic',this.fileList6)
},
}
}
</script>