|
|
<template>
|
|
|
<view class="survey-fill-page">
|
|
|
<image class="cbg" :src="base.imgHost('common_bg.png')"></image>
|
|
|
<!-- 进度条 -->
|
|
|
<view class="progress-bar-container">
|
|
|
<view class="progress-info">
|
|
|
<view class="progress-info-progress">
|
|
|
<u-line-progress :height="10" :percent="progressPercent" :show-percent="false"
|
|
|
active-color="#2018a0"></u-line-progress>
|
|
|
</view>
|
|
|
|
|
|
<text class="progress-text">{{ answeredCount }}/{{ questionList.length }}</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
<view class="survey-container">
|
|
|
|
|
|
<view class="survey-header">
|
|
|
<h1 class="survey-title">{{survey.title||''}}
|
|
|
</h1>
|
|
|
<p class="survey-description">
|
|
|
{{survey.desc||''}}
|
|
|
</p>
|
|
|
</view>
|
|
|
<!-- 问卷头部 -->
|
|
|
<!-- <view class="survey-header">
|
|
|
<view class="survey-header-item">
|
|
|
<view>
|
|
|
<span>课程名称</span>
|
|
|
<span>{{survey.name || ''}}</span>
|
|
|
</view>
|
|
|
<view v-if="!course_id">
|
|
|
<span>课程主题</span>
|
|
|
<span>{{survey.theme || ''}}</span>
|
|
|
</view>
|
|
|
<view v-if="!course_id">
|
|
|
<span>授课老师</span>
|
|
|
<span>{{survey.teacher?survey.teacher.name:''}}</span>
|
|
|
</view>
|
|
|
<view>
|
|
|
<span>授课时间</span>
|
|
|
<span v-if="course_id">{{survey.start_date || ''}} 至 {{survey.end_date || ''}}</span>
|
|
|
<span v-else>{{survey.date}} {{survey.start_time?survey.start_time:''}}-{{survey.end_time?survey.end_time:''}}</span>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view> -->
|
|
|
|
|
|
<!-- 问卷表单 -->
|
|
|
<view class="survey-form">
|
|
|
<view v-for="(q, index) in questionList" :key="q.id" class="question-item">
|
|
|
<view class="question-header">
|
|
|
<view class="question-number">{{ index + 1 }}</view>
|
|
|
<view class="question-title">
|
|
|
<text>{{ q.name }}</text>
|
|
|
<text v-if="q.rule && q.rule.includes('required')" class="required-mark">*</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
<view class="question-content">
|
|
|
<!-- 单选题 -->
|
|
|
<view v-if="q.edit_input === 'radio'">
|
|
|
<u-radio-group wrap v-model="q.value" @change="onValueChange">
|
|
|
<u-radio active-color="#2018a0" v-for="(opt, i) in q.select_item" :key="i"
|
|
|
:name="opt.value">{{ opt.value }}</u-radio>
|
|
|
</u-radio-group>
|
|
|
<u-input v-if="q.allow_input" v-model="q.allow_input_text" type="text"
|
|
|
:placeholder="'请输入'" />
|
|
|
</view>
|
|
|
|
|
|
<!-- 多选题 -->
|
|
|
<view v-if="q.edit_input === 'checkbox'">
|
|
|
<!-- @change="(e)=>{onValueChange(e,q)}" -->
|
|
|
<!-- <u-checkbox-group >
|
|
|
<u-checkbox @change="(e)=>{changeCheck(e,q.select_item)}" v-model="opt.checked" v-for="(opt, i) in q.select_item" :key="i"
|
|
|
:name="opt.value">{{ opt.value }}</u-checkbox>
|
|
|
</u-checkbox-group> -->
|
|
|
<checkbox-group style="display: flex;flex-wrap: wrap;"
|
|
|
@change="(e)=>{onValueChange(e,q)}">
|
|
|
<label style="flex-basis: 100%;margin-bottom:10rpx" v-for="(checkboxitem, checkboxindex) in q.select_item">
|
|
|
<checkbox activeBackgroundColor="#2018a0" :value="checkboxitem.value" :checked="checkboxitem.checked" />
|
|
|
{{checkboxitem.value}}
|
|
|
</label>
|
|
|
</checkbox-group>
|
|
|
<u-input v-if="q.allow_input" v-model="q.allow_input_text" type="text"
|
|
|
:placeholder="'请输入'" />
|
|
|
</view>
|
|
|
|
|
|
<!-- 文本题 -->
|
|
|
<u-input v-if="q.edit_input === 'text'" v-model="q.value" type="text"
|
|
|
:placeholder="q.help||'请输入'" @input="onValueChange" />
|
|
|
<!-- 文本域 -->
|
|
|
<u-input v-if="q.edit_input === 'textarea'" v-model="q.value" type="textarea"
|
|
|
:placeholder="q.help||'请输入'" :maxlength="9999" @input="onValueChange" />
|
|
|
<!-- 评分题 -->
|
|
|
<!-- <u-rate v-if="q.edit_input === 'rating'" v-model="answers[index]" :count="q.select_item.maxRating"
|
|
|
@change="onValueChange"></u-rate> -->
|
|
|
<!-- 量表题 -->
|
|
|
<!-- <view v-if="q.edit_input === 'scale'" class="scale-container">
|
|
|
<text>{{ q.select_item.min }}</text>
|
|
|
<u-slider v-model="answers[index]" :min="q.select_item.min" :max="q.select_item.max"
|
|
|
@end="onValueChange"></u-slider>
|
|
|
<text>{{ answers[index] || q.select_item.min }}</text>
|
|
|
</view> -->
|
|
|
<!-- 日期题 -->
|
|
|
<u-input v-if="q.edit_input === 'date'" v-model="q.value" type="text"
|
|
|
:placeholder="q.help||'请选择日期'" @click="openDatePicker(index)" />
|
|
|
|
|
|
<u-input v-if="q.edit_input === 'datetime'" v-model="q.value" type="text"
|
|
|
:placeholder="q.help||'请选择日期时间'" @click="openTimePicker(index)" />
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
<!-- 提交区域 -->
|
|
|
<view class="submit-section">
|
|
|
<!-- <u-button type="primary" shape="circle" @click="submitSurvey">
|
|
|
<u-icon name="send" class="btn-icon"></u-icon>
|
|
|
提交问卷
|
|
|
</u-button> -->
|
|
|
<view @click="submitSurvey" type="primary">提交</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
<!-- 日期选择器 -->
|
|
|
<u-picker v-model="showDatePicker" mode="time" @confirm="confirmDate"></u-picker>
|
|
|
<!-- 日期选择器 -->
|
|
|
<u-picker v-model="showTimePicker" mode="time" @confirm="confirmTime" :params="params"></u-picker>
|
|
|
</view>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
export default {
|
|
|
data() {
|
|
|
return {
|
|
|
id: '',
|
|
|
survey: {},
|
|
|
questionList: [],
|
|
|
answers: [],
|
|
|
isSubmit:false,
|
|
|
showDatePicker: false,
|
|
|
showTimePicker: false,
|
|
|
currentDateIndex: -1,
|
|
|
answeredCount: 0,
|
|
|
course_id:false,
|
|
|
params: {
|
|
|
year: true,
|
|
|
month: true,
|
|
|
day: true,
|
|
|
hour: true,
|
|
|
minute: true,
|
|
|
second: true
|
|
|
},
|
|
|
};
|
|
|
},
|
|
|
computed: {
|
|
|
progressPercent() {
|
|
|
if (!this.questionList.length) return 0;
|
|
|
return (this.answeredCount / this.questionList.length) * 100;
|
|
|
}
|
|
|
},
|
|
|
|
|
|
onLoad(options) {
|
|
|
// 获取页面参数
|
|
|
this.id = options.id
|
|
|
this.course_id = options.course_id
|
|
|
|
|
|
console.log("页面参数:", { id: this.id, course_id: this.course_id })
|
|
|
|
|
|
this.getDetail(this.id)
|
|
|
this.updateProgress();
|
|
|
},
|
|
|
methods: {
|
|
|
// 获取
|
|
|
async getDetail(id) {
|
|
|
// 检查传入的参数类型
|
|
|
// if (this.course_id) {
|
|
|
// // 如果参数是course_id,使用courseDetail接口
|
|
|
// const res = await this.$u.api.courseDetail({
|
|
|
// course_id: this.course_id
|
|
|
// })
|
|
|
// console.log("courseDetail res", res)
|
|
|
// this.survey = res
|
|
|
// } else {
|
|
|
// // 如果不是course_id,按之前的方式使用courseContentDetail接口
|
|
|
// const res = await this.$u.api.courseContentDetail({
|
|
|
// course_content_id: id
|
|
|
// })
|
|
|
// console.log("courseContentDetail res", res)
|
|
|
// this.survey = res
|
|
|
// }
|
|
|
|
|
|
const res = await this.$u.api.courseEvaluationDetail({
|
|
|
course_content_evaluation_id:id
|
|
|
})
|
|
|
console.log("courseEvaluationDetail res", res)
|
|
|
this.survey = res
|
|
|
|
|
|
// 检查是否有问卷调查数据
|
|
|
console.log("courseEvaluationDetail res", res.course_content_evaluation_asks)
|
|
|
if (res && res.course_content_evaluation_asks) {
|
|
|
this.questionList = res.course_content_evaluation_asks
|
|
|
} else {
|
|
|
this.questionList = []
|
|
|
console.warn("未找到问卷调查数据")
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 初始化答案数组
|
|
|
this.questionList.map(q => {
|
|
|
q.value = q.value?q.value:''
|
|
|
if (q.edit_input === 'checkbox') {
|
|
|
q.select_item.map(item=>{
|
|
|
item.checked = false
|
|
|
})
|
|
|
console.log("res", q)
|
|
|
};
|
|
|
if (q.allow_input) return q.allow_input_text = q.allow_input_text?q.allow_input_text:'';
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
updateProgress() {
|
|
|
let count = 0;
|
|
|
for (let i = 0; i < this.questionList.length; i++) {
|
|
|
const answer = this.questionList[i].value;
|
|
|
if (Array.isArray(answer) && answer.length > 0) {
|
|
|
count++;
|
|
|
} else if (!Array.isArray(answer) && answer !== '' && answer !== null && answer !== undefined) {
|
|
|
count++;
|
|
|
}
|
|
|
}
|
|
|
this.answeredCount = count;
|
|
|
},
|
|
|
onValueChange(e, item) {
|
|
|
console.log("value", e,item)
|
|
|
if(item){
|
|
|
if (e.detail.value.length > 0) {
|
|
|
item.value = e.detail.value.join(",")
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 在下一个事件循环更新进度,确保v-model生效
|
|
|
this.$nextTick(() => {
|
|
|
this.updateProgress();
|
|
|
});
|
|
|
},
|
|
|
openDatePicker(index) {
|
|
|
this.currentDateIndex = index;
|
|
|
this.showDatePicker = true;
|
|
|
},
|
|
|
confirmDate(e) {
|
|
|
console.log("e", e)
|
|
|
if (e) {
|
|
|
if (this.currentDateIndex !== -1) {
|
|
|
this.questionList[this.currentDateIndex].value = e.year + '-' + e.month + '-' + e.day
|
|
|
this.onValueChange();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
},
|
|
|
openTimePicker(index) {
|
|
|
this.currentDateIndex = index;
|
|
|
this.showTimePicker = true;
|
|
|
},
|
|
|
confirmTime(e) {
|
|
|
console.log("e", e)
|
|
|
if (e) {
|
|
|
if (this.currentDateIndex !== -1) {
|
|
|
this.questionList[this.currentDateIndex].value = e.year + '-' + e.month + '-' + e.day + ' ' + e
|
|
|
.hour + ':' + e.minute + ':' + e.second
|
|
|
this.onValueChange();
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
|
|
|
validateForm() {
|
|
|
console.log("this.questionList[i]", this.questionList)
|
|
|
// return
|
|
|
// for (let i = 0; i < this.questionList.length; i++) {
|
|
|
// const q = this.questionList[i];
|
|
|
// const answer = this.answers[i];
|
|
|
// if (q.required) {
|
|
|
// const isEmpty = Array.isArray(answer) ? answer.length === 0 : (answer === '' || answer === null ||
|
|
|
// answer === undefined);
|
|
|
// if (isEmpty) {
|
|
|
// uni.showToast({
|
|
|
// title: `请完成第 ${i + 1} 题`,
|
|
|
// icon: 'none'
|
|
|
// });
|
|
|
// return false;
|
|
|
// }
|
|
|
// }
|
|
|
// }
|
|
|
let errorCount = 0
|
|
|
this.questionList.map(item => {
|
|
|
if (item.rule) {
|
|
|
// 不能为空
|
|
|
if (item.rule.indexOf('required') !== -1) {
|
|
|
if (this.base.isNull(item.value)) {
|
|
|
this.base.toast(`${item.name}不能为空`)
|
|
|
errorCount++
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
// 手机号
|
|
|
if (!this.base.isNull(item.value) && item.rule.indexOf('mobile') !== -1) {
|
|
|
if (!this.base.isMobile(item.value)) {
|
|
|
this.base.toast(`${item.name}不正确`)
|
|
|
errorCount++
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
// 身份证
|
|
|
if (!this.base.isNull(item.value) && item.rule.indexOf('idcard') !== -1) {
|
|
|
if (!this.$u.test.idCard(item.value)) {
|
|
|
this.base.toast(`${item.name}不正确`)
|
|
|
errorCount++
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
// 邮箱
|
|
|
if (item.rule.indexOf('email') !== -1) {
|
|
|
if (!this.base.isNull(item.value) && !this.base.isMail(item.value)) {
|
|
|
this.base.toast(`${item.name}不正确`)
|
|
|
errorCount++
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
// 整数
|
|
|
if (item.rule.indexOf('integer') !== -1) {
|
|
|
if (!this.base.isNull(item.value) && !this.base.isInteger(item.value)) {
|
|
|
this.base.toast(`${item.name}必须为整数`)
|
|
|
errorCount++
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
// 数字
|
|
|
if (item.rule.indexOf('numeric') !== -1) {
|
|
|
if (!this.base.isNull(item.value) && !this.base.isNumber(item.value)) {
|
|
|
this.base.toast(`${item.name}必须为数字`)
|
|
|
errorCount++
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
})
|
|
|
if (errorCount > 0) {
|
|
|
return
|
|
|
}
|
|
|
return true;
|
|
|
},
|
|
|
submitSurvey() {
|
|
|
if (!this.validateForm()) {
|
|
|
return;
|
|
|
}
|
|
|
let that = this
|
|
|
if(this.isSubmit){
|
|
|
return
|
|
|
}
|
|
|
this.isSubmit = true
|
|
|
uni.showModal({
|
|
|
title: '提交确认',
|
|
|
content: '确定要提交问卷吗?',
|
|
|
success: (res) => {
|
|
|
if (res.confirm) {
|
|
|
that.$u.api.courseContentForm({
|
|
|
course_content_evaluation_id:that.id,
|
|
|
data:that.questionList
|
|
|
}).then(res=>{
|
|
|
that.base.toast('提交成功',1500,function(){
|
|
|
that.isSubmit = false
|
|
|
uni.navigateBack(-1)
|
|
|
})
|
|
|
}).catch(err=>{
|
|
|
that.isSubmit = false
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
.survey-fill-page {
|
|
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
|
// background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
height: 100vh;
|
|
|
overflow: scroll;
|
|
|
}
|
|
|
.cbg {
|
|
|
position: absolute;
|
|
|
top: 0;
|
|
|
left: 0;
|
|
|
width: 100%;
|
|
|
height: 100vh;
|
|
|
}
|
|
|
.survey-container {
|
|
|
margin: 0 auto;
|
|
|
padding: 30rpx;
|
|
|
padding-top: 100rpx;
|
|
|
position: relative;
|
|
|
|
|
|
}
|
|
|
|
|
|
.survey-header {
|
|
|
background: white;
|
|
|
border-radius: 24rpx;
|
|
|
padding: 40rpx;
|
|
|
margin-bottom: 30rpx;
|
|
|
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
|
|
|
font-size: 28rpx;
|
|
|
padding-bottom: 20rpx;
|
|
|
|
|
|
&-item {
|
|
|
color: #666;
|
|
|
|
|
|
&>view {
|
|
|
display: flex;
|
|
|
margin-bottom: 40rpx;
|
|
|
|
|
|
&>span:first-child {
|
|
|
color: #000;
|
|
|
margin-right: 20rpx;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.survey-title {
|
|
|
font-size: 44rpx;
|
|
|
font-weight: 700;
|
|
|
margin-bottom: 24rpx;
|
|
|
text-align: center;
|
|
|
}
|
|
|
|
|
|
.survey-description {
|
|
|
font-size: 28rpx;
|
|
|
color: #6c757d;
|
|
|
line-height: 1.6;
|
|
|
margin-bottom: 30rpx;
|
|
|
}
|
|
|
|
|
|
.survey-meta {
|
|
|
display: flex;
|
|
|
justify-content: center;
|
|
|
gap: 30rpx;
|
|
|
flex-wrap: wrap;
|
|
|
font-size: 24rpx;
|
|
|
color: #6c757d;
|
|
|
}
|
|
|
|
|
|
.meta-item {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
gap: 8rpx;
|
|
|
}
|
|
|
|
|
|
.progress-bar-container {
|
|
|
background: white;
|
|
|
padding: 20rpx 30rpx;
|
|
|
margin-bottom: 30rpx;
|
|
|
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
|
|
|
position: fixed;
|
|
|
width: 100%;
|
|
|
top: 0;
|
|
|
left: 0;
|
|
|
z-index: 99;
|
|
|
}
|
|
|
|
|
|
.progress-info {
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
align-items: center;
|
|
|
font-size: 24rpx;
|
|
|
color: #2018a0;
|
|
|
|
|
|
&-progress {
|
|
|
width: calc(100% - 50rpx)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.survey-form {}
|
|
|
|
|
|
.question-item {
|
|
|
// padding: 30rpx 0;
|
|
|
// border-bottom: 1rpx solid #e9ecef;
|
|
|
background: white;
|
|
|
border-radius: 24rpx;
|
|
|
padding: 40rpx 20rpx;
|
|
|
margin-bottom: 30rpx;
|
|
|
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
|
|
|
font-size: 28rpx;
|
|
|
}
|
|
|
|
|
|
.question-item:last-child {
|
|
|
border-bottom: none;
|
|
|
}
|
|
|
|
|
|
.question-header {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
gap: 20rpx;
|
|
|
margin-bottom: 24rpx;
|
|
|
}
|
|
|
|
|
|
.question-number {
|
|
|
background: #bf976e;
|
|
|
color: white;
|
|
|
width: 60rpx;
|
|
|
height: 60rpx;
|
|
|
border-radius: 50%;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
font-size: 28rpx;
|
|
|
font-weight: 600;
|
|
|
flex-shrink: 0;
|
|
|
}
|
|
|
|
|
|
.question-title {
|
|
|
font-size: 28rpx;
|
|
|
font-weight: 600;
|
|
|
color: #333;
|
|
|
line-height: 1.4;
|
|
|
flex: 1;
|
|
|
}
|
|
|
|
|
|
.required-mark {
|
|
|
color: #e74c3c;
|
|
|
margin-left: 8rpx;
|
|
|
}
|
|
|
|
|
|
.question-content {
|
|
|
// padding-left: 64rpx;
|
|
|
}
|
|
|
|
|
|
.scale-container {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
gap: 20rpx;
|
|
|
color: #666;
|
|
|
}
|
|
|
|
|
|
.submit-section {
|
|
|
width: 100%;
|
|
|
position: relative;
|
|
|
padding: 60rpx 0;
|
|
|
|
|
|
&>view {
|
|
|
width: 70%;
|
|
|
text-align: center;
|
|
|
margin: 0 auto;
|
|
|
color: #fff;
|
|
|
background: linear-gradient(to right, #5e5fbc, #0d0398);
|
|
|
border-radius: 30rpx;
|
|
|
padding: 20rpx;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.btn-icon {
|
|
|
margin-right: 10rpx;
|
|
|
}
|
|
|
</style> |