You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

533 lines
14 KiB

5 months ago
<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.course_content_evaluation?survey.course_content_evaluation.title:''}}
</h1>
<p class="survey-description">
{{survey.course_content_evaluation?survey.course_content_evaluation.desc:''}}
</p>
</view>
<!-- 问卷头部 -->
<view class="survey-header">
<view class="survey-header-item">
<view>
<span>课程名称</span>
<span>{{survey.course.name}}</span>
</view>
<view>
<span>课程主题</span>
<span>{{survey.theme}}</span>
</view>
<view>
<span>授课老师</span>
<span>{{survey.teacher?survey.teacher.name:''}}</span>
</view>
<view>
<span>授课时间</span>
5 months ago
<span>{{survey.date}} {{survey.start_time?survey.start_time:''}}-{{survey.end_time?survey.end_time:''}}</span>
5 months ago
</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,
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.getDetail(this.id)
this.updateProgress();
},
methods: {
// 获取
async getDetail(id) {
const res = await this.$u.api.courseContentDetail({
course_content_id: id
})
console.log("res", res)
this.survey = res
this.questionList = res.course_content_evaluation.course_content_evaluation_asks
//
// 初始化答案数组
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.survey.course_content_evaluation.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>