Browse Source

调查问卷优化

fengyu 2 months ago
parent
commit
74bbc0ce16
1 changed files with 155 additions and 26 deletions
  1. 155 26
      src/pages/questionnaire.vue

+ 155 - 26
src/pages/questionnaire.vue

@@ -3,7 +3,7 @@
3
  * @Author: Fengyu
3
  * @Author: Fengyu
4
  * @Date: 2025-12-12 10:12:59
4
  * @Date: 2025-12-12 10:12:59
5
  * @LastEditors: Fengyu
5
  * @LastEditors: Fengyu
6
- * @LastEditTime: 2025-12-17 14:29:31
6
+ * @LastEditTime: 2025-12-17 17:32:29
7
 -->
7
 -->
8
 <template>
8
 <template>
9
   <view class="questionnaire-container">
9
   <view class="questionnaire-container">
@@ -33,9 +33,20 @@
33
     <!-- 网格选择区域 -->
33
     <!-- 网格选择区域 -->
34
     <view class="grid-section">
34
     <view class="grid-section">
35
       <view class="grid-container">
35
       <view class="grid-container">
36
+
37
+        <view class="grid-item">
38
+          <view class="grid-content flex j-sb a-center">
39
+            <view class="grid-title">1.您的身份是:</view>
40
+            <view class="grid-desc">
41
+              <u-select v-model="userTypeShow" :list="userTypeList" @confirm="userTypeconfirm"></u-select>
42
+              <span @click="userTypeShow = true">{{ userTypeName || '请选择' }}&nbsp;<span style="position: relative; top: -2px;">⌵</span></span>
43
+            </view>
44
+          </view>
45
+        </view>
46
+
36
         <view class="grid-item">
47
         <view class="grid-item">
37
           <view class="grid-content flex j-sb a-center">
48
           <view class="grid-content flex j-sb a-center">
38
-            <view class="grid-title">1.您所在的服务区</view>
49
+            <view class="grid-title">2.您所在的服务区</view>
39
             <view class="grid-desc">
50
             <view class="grid-desc">
40
               <u-select v-model="parkSelectShow" :list="parkList" @confirm="confirm"></u-select>
51
               <u-select v-model="parkSelectShow" :list="parkList" @confirm="confirm"></u-select>
41
               <span @click="parkSelectShow = true">{{ parkName || '请选择' }}&nbsp;<span style="position: relative; top: -2px;">⌵</span></span>
52
               <span @click="parkSelectShow = true">{{ parkName || '请选择' }}&nbsp;<span style="position: relative; top: -2px;">⌵</span></span>
@@ -44,7 +55,7 @@
44
         </view>
55
         </view>
45
         <view v-for="(item, index) in dataFilledIn" :key="item.id" class="grid-item">
56
         <view v-for="(item, index) in dataFilledIn" :key="item.id" class="grid-item">
46
           <view class="grid-content">
57
           <view class="grid-content">
47
-            <view class="grid-title">{{ index + 2 }}. {{ item.name }}</view>
58
+            <view class="grid-title">{{ index + 3 }}. {{ item.name }}</view>
48
             <view class="grid-desc">
59
             <view class="grid-desc">
49
               <u-radio-group v-model="item.value">
60
               <u-radio-group v-model="item.value">
50
                 <u-radio
61
                 <u-radio
@@ -61,7 +72,7 @@
61
         <!-- 最好的高速 -->
72
         <!-- 最好的高速 -->
62
         <view class="grid-item">
73
         <view class="grid-item">
63
           <view class="grid-content">
74
           <view class="grid-content">
64
-            <view class="grid-title">{{ dataFilledIn.length + 2 }}. 您认为途经最好的高速是?</view>
75
+            <view class="grid-title">{{ dataFilledIn.length + 3 }}. 您认为途经最好的高速是?</view>
65
             <view class="grid-desc">
76
             <view class="grid-desc">
66
               <u-input v-model="bestWay" type="textarea" :border="false" :height="100" :auto-height="true" placeholder="请输入您认为途经最好的高速" />
77
               <u-input v-model="bestWay" type="textarea" :border="false" :height="100" :auto-height="true" placeholder="请输入您认为途经最好的高速" />
67
             </view>
78
             </view>
@@ -70,13 +81,23 @@
70
         <!-- 最好的服务区 -->
81
         <!-- 最好的服务区 -->
71
         <view class="grid-item">
82
         <view class="grid-item">
72
           <view class="grid-content">
83
           <view class="grid-content">
73
-            <view class="grid-title">{{ dataFilledIn.length + 3 }}. 您认为途经最好的服务区是?</view>
84
+            <view class="grid-title">{{ dataFilledIn.length + 4 }}. 您认为途经最好的服务区是?</view>
74
             <view class="grid-desc">
85
             <view class="grid-desc">
75
               <u-input v-model="bestService" type="textarea" :border="false" :height="100" :auto-height="true" placeholder="请输入您认为途经最好的服务区" />
86
               <u-input v-model="bestService" type="textarea" :border="false" :height="100" :auto-height="true" placeholder="请输入您认为途经最好的服务区" />
76
             </view>
87
             </view>
77
           </view>
88
           </view>
78
         </view>
89
         </view>
79
 
90
 
91
+        <!-- 宝贵意见 -->
92
+        <view class="grid-item">
93
+          <view class="grid-content">
94
+            <view class="grid-title">{{ dataFilledIn.length + 5 }}. 宝贵意见</view>
95
+            <view class="grid-desc">
96
+              <u-input v-model="opinion" type="textarea" :border="false" :height="100" :auto-height="true" placeholder="请输入宝贵意见" />
97
+            </view>
98
+          </view>
99
+        </view>
100
+
80
         <view class="grid-item">
101
         <view class="grid-item">
81
           <view class="grid-content">
102
           <view class="grid-content">
82
             <view class="grid-title">您的手机号:</view>
103
             <view class="grid-title">您的手机号:</view>
@@ -86,8 +107,15 @@
86
           </view>
107
           </view>
87
         </view>
108
         </view>
88
 
109
 
89
-        <view class="submit-btn" @click="submitForm">
90
-          提 交
110
+        <view 
111
+          class="submit-btn" 
112
+          @click="submitForm" 
113
+          :class="{ 'disabled': !isFormAvailable || isSubmitting || submitCountdown > 0 }" 
114
+          :disabled="!isFormAvailable || isSubmitting || submitCountdown > 0"
115
+        >
116
+          <span v-if="!isSubmitting && submitCountdown === 0">提 交</span>
117
+          <span v-else-if="isSubmitting">提交中...</span>
118
+          <span v-else>稍后提交({{ submitCountdown }}s)</span>
91
         </view>
119
         </view>
92
       </view>
120
       </view>
93
     </view>
121
     </view>
@@ -97,7 +125,7 @@
97
         <view class="rect" @tap.stop>
125
         <view class="rect" @tap.stop>
98
           <view class="rect-content">
126
           <view class="rect-content">
99
             <view class="rect-title">提示</view>
127
             <view class="rect-title">提示</view>
100
-            <view class="rect-desc">当前时间已超过截止时间,无法填写</view>
128
+            <view class="rect-desc">{{ msg || '当前时间已超过截止时间,无法填写' }}</view>
101
             <view class="rect-btn" @click="goHome">去首页</view>
129
             <view class="rect-btn" @click="goHome">去首页</view>
102
           </view>
130
           </view>
103
         </view>
131
         </view>
@@ -178,6 +206,34 @@
178
 
206
 
179
   const phone = ref('')
207
   const phone = ref('')
180
 
208
 
209
+  const userTypeShow = ref(false)
210
+  const userTypeList = ref([
211
+    {
212
+      label: '大客司机',
213
+      value: 1
214
+    },
215
+    {
216
+      label: '大客乘客',
217
+      value: 2
218
+    },
219
+    {
220
+      label: '小客司乘人员',
221
+      value: 3
222
+    },
223
+    {
224
+      label: '货车司机',
225
+      value: 4
226
+    },
227
+    {
228
+      label: '其他',
229
+      value: 5
230
+    }
231
+  ])
232
+  const userTypeName = ref('')
233
+  const userType = ref('')
234
+
235
+  const opinion = ref('')
236
+
181
   // 获取服务区列表
237
   // 获取服务区列表
182
   const getParkListApi = () => {
238
   const getParkListApi = () => {
183
     getParkList().then(res => {
239
     getParkList().then(res => {
@@ -201,6 +257,13 @@
201
     });
257
     });
202
   }
258
   }
203
 
259
 
260
+  // 选择用户身份
261
+  const userTypeconfirm = (e) => {
262
+    console.log(e[0].value, e[0].label)
263
+    userTypeName.value = e[0].label
264
+    userType.value = e[0].value
265
+  }
266
+
204
   // 选择服务区
267
   // 选择服务区
205
   const confirm = (e) => {
268
   const confirm = (e) => {
206
     console.log(e[0].value, e[0].label)
269
     console.log(e[0].value, e[0].label)
@@ -230,6 +293,10 @@
230
   // 是否超时,超时显示弹窗
293
   // 是否超时,超时显示弹窗
231
   const isFormAvailable = ref(true)
294
   const isFormAvailable = ref(true)
232
 
295
 
296
+  // 提交按钮相关状态
297
+  const isSubmitting = ref(false) // 是否正在提交
298
+  const submitCountdown = ref(0) // 提交倒计时(秒)
299
+
233
   /**
300
   /**
234
    * 验证问卷截止时间
301
    * 验证问卷截止时间
235
    * @param {string} endAt 截止时间字符串,格式为"YYYY-MM-DD HH:MM:SS"
302
    * @param {string} endAt 截止时间字符串,格式为"YYYY-MM-DD HH:MM:SS"
@@ -259,6 +326,27 @@
259
     })
326
     })
260
   }
327
   }
261
 
328
 
329
+  const msg = ref('')
330
+
331
+  /**
332
+   * 开始提交倒计时,限制5秒内只能提交一次
333
+   */
334
+  const startSubmitCountdown = () => {
335
+    const countdownTime = 5; // 倒计时时间(秒)
336
+    submitCountdown.value = countdownTime;
337
+    
338
+    // 创建倒计时定时器
339
+    const timer = setInterval(() => {
340
+      submitCountdown.value--;
341
+      
342
+      // 倒计时结束
343
+      if (submitCountdown.value <= 0) {
344
+        clearInterval(timer);
345
+        submitCountdown.value = 0;
346
+      }
347
+    }, 1000);
348
+  }
349
+
262
   // 根据页面参数获取问卷详情
350
   // 根据页面参数获取问卷详情
263
   onMounted(() => {
351
   onMounted(() => {
264
     getParkListApi()
352
     getParkListApi()
@@ -285,32 +373,52 @@
285
           dataFilledIn.value = dataList.value
373
           dataFilledIn.value = dataList.value
286
         }
374
         }
287
       } else {
375
       } else {
288
-        uni.showToast({
289
-          title: res.message || '获取问卷详情失败',
290
-          icon: 'none'
291
-        });
376
+        msg.value = res.msg || '获取问卷详情失败'
377
+        isFormAvailable.value = false
378
+        // uni.showToast({
379
+        //   title: res.message || '获取问卷详情失败',
380
+        //   icon: 'none'
381
+        // });
292
       }
382
       }
293
     }).catch(err => {
383
     }).catch(err => {
294
-      console.error('获取问卷详情失败:', err);
295
-      uni.showToast({
296
-        title: '网络错误,请重试',
297
-        icon: 'none'
298
-      });
384
+      // console.error('获取问卷详情失败:', err);
385
+      uni.hideToast()
386
+      msg.value = err.data.msg || '获取问卷详情失败'
387
+      isFormAvailable.value = false
388
+      // uni.showToast({
389
+      //   title: '网络错误,请重试',
390
+      //   icon: 'none'
391
+      // });
299
     });
392
     });
300
   });
393
   });
301
   
394
   
302
     // 提交表单
395
     // 提交表单
303
     const submitForm = () => {
396
     const submitForm = () => {
397
+      // 检查表单是否可用
398
+      if (!isFormAvailable.value) {
399
+        uni.showToast({
400
+          title: '当前时间已超过截止时间,无法提交',
401
+          icon: 'none'
402
+        });
403
+        return;
404
+      }
405
+      
406
+      // 检查是否正在提交或处于倒计时状态
407
+      if (isSubmitting.value || submitCountdown.value > 0) {
408
+        return;
409
+      }
410
+      
304
       // 检查是否所有项都有选择
411
       // 检查是否所有项都有选择
305
       const isComplete = dataFilledIn.value.every(item => item.value !== '');
412
       const isComplete = dataFilledIn.value.every(item => item.value !== '');
306
-      if (!isComplete) {
413
+
414
+      if (!userType.value) {
307
         uni.showToast({
415
         uni.showToast({
308
-          title: '请完成所有项',
416
+          title: '请选择身份',
309
           icon: 'none'
417
           icon: 'none'
310
         });
418
         });
311
         return;
419
         return;
312
       }
420
       }
313
-
421
+      
314
       if (!parkId.value) {
422
       if (!parkId.value) {
315
         uni.showToast({
423
         uni.showToast({
316
           title: '请选择服务区',
424
           title: '请选择服务区',
@@ -318,6 +426,14 @@
318
         });
426
         });
319
         return;
427
         return;
320
       }
428
       }
429
+
430
+      if (!isComplete) {
431
+        uni.showToast({
432
+          title: '请完成所有项',
433
+          icon: 'none'
434
+        });
435
+        return;
436
+      }
321
       
437
       
322
       if (!phone.value) {
438
       if (!phone.value) {
323
         uni.showToast({
439
         uni.showToast({
@@ -389,11 +505,16 @@
389
         questionnaireId,
505
         questionnaireId,
390
         // parkid, // 使用API要求的参数名
506
         // parkid, // 使用API要求的参数名
391
         mobile: phone.value,
507
         mobile: phone.value,
508
+        userType: userType.value,
509
+        opinion: opinion.value,
392
         ...scoreData
510
         ...scoreData
393
       };
511
       };
394
 
512
 
395
       console.log('提交参数:', params);
513
       console.log('提交参数:', params);
396
       
514
       
515
+      // 设置提交状态
516
+      isSubmitting.value = true;
517
+      
397
       // 调用API提交表单
518
       // 调用API提交表单
398
       submitQuestionnaireApi(params).then(res => {
519
       submitQuestionnaireApi(params).then(res => {
399
         if (res.code === 200) {
520
         if (res.code === 200) {
@@ -401,6 +522,8 @@
401
             title: '感谢您的反馈!',
522
             title: '感谢您的反馈!',
402
             icon: 'success'
523
             icon: 'success'
403
           });
524
           });
525
+          // 提交成功后开始5秒倒计时
526
+          startSubmitCountdown();
404
           setTimeout(() => {
527
           setTimeout(() => {
405
             uni.switchTab({
528
             uni.switchTab({
406
               url: '/pages/index'
529
               url: '/pages/index'
@@ -418,6 +541,9 @@
418
           title: err.data.msg || '操作失败',
541
           title: err.data.msg || '操作失败',
419
           icon: 'none'
542
           icon: 'none'
420
         });
543
         });
544
+      }).finally(() => {
545
+        // 无论成功失败,都恢复提交状态
546
+        isSubmitting.value = false;
421
       });
547
       });
422
     }
548
     }
423
 </script>
549
 </script>
@@ -517,6 +643,7 @@
517
     display: flex;
643
     display: flex;
518
     flex-direction: column;
644
     flex-direction: column;
519
     margin-bottom: 40rpx;
645
     margin-bottom: 40rpx;
646
+    padding-bottom: 10px;
520
 
647
 
521
     .grid-content {
648
     .grid-content {
522
 
649
 
@@ -529,16 +656,18 @@
529
 
656
 
530
     // 提交按钮
657
     // 提交按钮
531
     .submit-btn {
658
     .submit-btn {
532
-      width: 100%;
533
-      height: 80rpx;
534
-      line-height: 80rpx;
659
+      width: calc(100% - 20px);
660
+      margin: auto;
661
+      height: 2.5rem;
662
+      line-height: 2.5rem;
535
       text-align: center;
663
       text-align: center;
536
-      font-size: 32rpx;
664
+      font-size: 1rem;
537
       font-weight: 600;
665
       font-weight: 600;
538
       color: #fff;
666
       color: #fff;
539
       background: linear-gradient(to bottom, #7EBBF5, #4B9EF6);
667
       background: linear-gradient(to bottom, #7EBBF5, #4B9EF6);
540
-      border-radius: 10rpx;
541
-      margin-top: 40rpx;
668
+      border-radius: 0.3125rem;
669
+      margin-top: 1.25rem;
670
+      padding: 0 10px;
542
       // position: absolute;
671
       // position: absolute;
543
       // bottom: 0;
672
       // bottom: 0;
544
       // left: 0;
673
       // left: 0;