董国庆
2 天以前 df64b8405927e7fe3f9cfbae1f628b2d3b7a0f64
H5/pages/Appeal/Appeal.vue
@@ -3,22 +3,24 @@
      <view class="main">
         <view class="card  flex a-center h-108 j-between">
            <text class="w-108 fs-27 font-bold mr-85">发生时间</text>
            <view class=" flex a-center j-between flex1" @click="showDate=true">
               <view class="flex1" v-if="time">
                  {{time}}
            <view class=" flex a-center j-between flex1" @click="showDate = true">
               <view class=" flex a-center j-between flex1">
                  <view class="flex1" v-if="time">
                     {{ time }}
                  </view>
                  <view class="flex1" v-else style="color: rgba(0,0,0,0.3);font-size:27rpx;">
                     请选择问题发生的时间
                  </view>
                  <image src="/static/Appeal/left.png" class="w-19 h-19" mode=""></image>
               </view>
               <view class="flex1" v-else style="color: rgba(0,0,0,0.3);font-size:27rpx;">
                  请选择问题发生的时间
               </view>
               <image src="/static/Appeal/left.png" class="w-19 h-19" mode=""></image>
            </view>
         </view>
         <view class="card  flex a-center h-108 j-between">
            <text class="w-108 fs-27 font-bold mr-85">问题类型</text>
            <view class=" flex a-center j-between flex1" @click="showList=true">
            <view class=" flex a-center j-between flex1" @click="showList = true">
               <view class="flex1" v-if="problemType">
                  {{problemType}}
                  {{ problemType }}
               </view>
               <view class="flex1" v-else style="color: rgba(0,0,0,0.3);font-size:27rpx;">
                  请选择问题类型
@@ -38,12 +40,12 @@
               class="uni-input flex1" maxlength="11" placeholder="请输入群众联系电话" />
         </view>
         <view class="card  flex a-center h-108 j-between" @click="goTopagelocation()">
            <text class="w-108 fs-27 font-bold mr-85">地点</text>
         <view class="card  flex min-108 a-center j-between" @click="goTopagelocation()">
            <text class="w-108 fs-27 font-bold mr-85">发生地点</text>
            <view class=" flex a-center j-between flex1">
               <view class="flex1" v-if="location">
                  {{location}}
               <view class="flex1 address line2" v-if="location">
                  {{ location }}
               </view>
               <view class="flex1" v-else style="color: rgba(0,0,0,0.3);font-size:27rpx;">
                  请选择问题发生具体地点
@@ -57,21 +59,42 @@
               class="uni-input flex1" placeholder="请输入详细地址描述" />
         </view>
         <view class="mt-35">
            <text class="w-108 fs-27 font-bold mr-85">问题描述</text>
            <view class="flex a-center j-between">
               <text class="w-108 fs-27 font-bold mr-85">问题描述</text>
               <view class="flex a-center" @click="voiceInput">
                  <image src="/static/Appeal/yuyin.png" class="w-30 h-30 mr-11" mode=""></image>
                  <text class="fs-23 red">语音输入</text>
               </view>
            </view>
            <view v-for="item, index in videoContent" :key="index">
               <view class="pl-19 pr-19 pb-17 pt-17 flex j-between a-center br-8 pink">
                  <view class="flex1">
                     <text class="fs-27 font-bold">语音文件{{ index + 1 }}</text>
                  </view>
                  <view class="flex j-between a-center">
                     <image src="/static/Appeal/delete.png" class="w-27 h-27 mr-38" mode=""></image>
                     <image src="/static/Appeal/open.png" class="w-27 h-27" mode="" v-if="!item.playing"
                        @click.stop="onPlayRecording(index)"></image>
                     <image src="/static/Appeal/pause.png" class="w-27 h-27" mode="" v-else
                        @click.stop="onPausePlaying(index)"></image>
                  </view>
               </view>
            </view>
            <view class="bg mt-27 fs-27">
               <view class="h-94 " style="border-bottom: 2rpx solid rgba(0, 10, 26, 0.07);">
               <!-- <view class="h-94 " style="border-bottom: 2rpx solid rgba(0, 10, 26, 0.07);">
                  <input v-model="descriptionTitle" placeholder-style="color: rgba(0,0,0,0.3);font-size:27rpx;"
                     class="h-94 pl-31 flex1" placeholder="请输入问题标题" />
               </view>
               </view> -->
               <textarea name="" v-model="descriptionContent" id="" cols="30" placeholder="请输入问题描述内容"
                  placeholder-style="color: rgba(0, 0, 0, 0.30);font-size:27rpx;" rows="10"></textarea>
            </view>
         </view>
         <view class="mt-35">
            <text class="w-108 fs-27 font-bold mr-85">图片</text>
            <view class="mt-27 flex a-center">
               <view class="img mr-15" v-for="item,index in images" :key="index">
            <text class="w-108 fs-27 font-bold mr-85">上传图片</text>
            <view class="mt-27 flex a-center flex" style="flex-wrap: wrap;">
               <view class="img mr-15" v-for="item, index in images" :key="index">
                  <image :src="item" class="w-140 h-140" mode=""></image>
                  <view class="img-icon">
                     <image class="w-19 h-19" @click="previewImage(index)" src="/static/Appeal/amplify.png"
@@ -85,9 +108,9 @@
            </view>
         </view>
         <view class="mt-35">
            <text class="w-108 fs-27 font-bold mr-85">视频</text>
            <view class="mt-27 flex a-center">
               <view class="img mr-15" v-for="item,index in videos" :key="index">
            <text class="w-108 fs-27 font-bold mr-85">上传视频</text>
            <view class="mt-27 flex a-center flex" style="flex-wrap: wrap;">
               <view class="img mr-15" v-for="item, index in videos" :key="index">
                  <video :controls="false" :show-center-play-btn="false" :src="item" class="w-140 h-140"
                     mode=""></video>
                  <view class="img-icon">
@@ -101,13 +124,24 @@
            </view>
         </view>
      </view>
      <view class="btn" @click="submit">
         保存
      <view class="footer">
         <view class="cancel" @click="submit(1)">
            问题上报
         </view>
         <view class="cancel" @click="submit(2)">
            办理结果录入
         </view>
         <view class="ok" @click="submit(3)">
            保存
         </view>
      </view>
      <u-datetime-picker :show="showDate" v-model="value1" mode="date" :closeOnClickOverlay="true"
         @confirm="confirmone" @close="close" @cancel="cancel"></u-datetime-picker>
      <u-picker :show="showList" :columns="columns" @confirm="confirmtwo" :closeOnClickOverlay="true" @close="close"
         @cancel="cancel"></u-picker>
      <!-- 语音输入弹窗 -->
      <voiceInputPopup :show="voiceInputShow" @update:show="voiceInputShow = $event" @close="closeVoiceInput"
         @submit="submitVoiceInput" />
   </view>
</template>
@@ -117,8 +151,17 @@
      save,
      getproblem
   } from './service.js'
   import config from '@/config/index.js'
   import voiceInputPopup from '@/components/voiceInputPopup.vue'
   import {
      mapActions,
      mapState
   } from "vuex";
   export default {
      components: {
         voiceInputPopup
      },
      data() {
         return {
            showList: false,
@@ -131,20 +174,62 @@
            problemType: '',
            name: '',
            contactNumber: '',
            location: '',
            detailedAddress: '',
            descriptionTitle: '',
            descriptionContent: '',
            latitude: '',
            longitude: '',
            videoContent: [],
            latitude: '30.5061493',
            longitude: '105.574542',
            location: '测试地址',
            images: [],
            videos: [],
            voiceFile: '', //语音文件多个逗号拼接
            userInfo: uni.getStorageSync('userInfo'), //个人信息
            voiceInputShow: false,
         };
      },
      computed: {
         ...mapState(["playFlag"]),
      },
      onReady() {
         uni.setNavigationBarTitle({
            title: '诉求录入'
         })
      },
      onLoad() {
         this.getproblem()
         this.time = dayjs().format('YYYY-MM-DD')
      },
      methods: {
         ...mapActions(["playRecording", "pausePlaying"]),
         onPlayRecording(index) {
            // 先处理本地播放状态
            this.videoContent.forEach((item, i) => {
               item.playing = i === index;
            });
            // 调用store的播放方法,传url
            this.playRecording(this.videoContent[index].url);
         },
         onPausePlaying(index) {
            this.videoContent[index].playing = false;
            this.pausePlaying(this.videoContent[index].url);
         },
         voiceInput() {
            this.voiceInputShow = true;
         },
         closeVoiceInput() {
            this.voiceInputShow = false;
         },
         submitVoiceInput(e) {
            console.log('eeeeeeeeeeeeeeeeeee', e)
            this.videoContent.push({
               url: e.url,
               data: e.data,
               playing: false
            });
            this.voiceInputShow = false;
         },
         previewImage(index) {
            uni.previewImage({
               urls: this.images,
@@ -152,10 +237,10 @@
               longPressActions: {
                  itemList: ['发送给朋友', '保存图片', '收藏'],
                  success: function(data) {
                     console.log('选中了第' + (data.tapIndex + 1) + '个按钮,第' + (data.index + 1) + '张图片');
                  },
                  fail: function(err) {
                     console.log(err.errMsg);
                  }
               }
            });
@@ -174,13 +259,83 @@
         },
         getproblem() {
            getproblem().then((resp => {
               console.log(resp, '问题类型')
               this.columns = [resp.data.map(item => {
                  return item.name
               })]
            }))
         },
         submit() {
         async submit(type) {
            if (this.videoContent.length > 0) {
               uni.showLoading({
                  title: '正在上传语音文件...'
               });
               const uploadPromises = this.videoContent.map(item => {
                  return new Promise((resolve, reject) => {
                     console.log('item.data', item.data)
                     // uni.chooseAudio({
                     //    success:  (res)=> {
                     //       console.log(res.tempFilePaths[0]);
                     //       uni.uploadFile({
                     //          url: config.imageUrl,
                     //          filePath: res.tempFilePaths[0],  // 使用 Blob 数据
                     //          name: 'file',
                     //          header: {
                     //             // 'Content-Type': 'multipart/form-data',
                     //             'Authorization': uni.getStorageSync('token')
                     //          },
                     //          success: (uploadFileRes) => {
                     //             const response = JSON.parse(uploadFileRes.data);
                     //             if (response.code === 200) {
                     //                resolve(response.data);
                     //             } else {
                     //                reject(new Error('上传失败'));
                     //             }
                     //          },
                     //          fail: (error) => {
                     //             reject(error);
                     //          }
                     //       });
                     //    }
                     // });
                     uni.uploadFile({
                        url: config.imageUrl,
                        file: item.data, // 使用 Blob 数据
                        name: 'file',
                        header: {
                           // 'Content-Type': 'multipart/form-data',
                           'Authorization': 'Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOjE4OTU1MjI1Nzk1MDcwODEyMTgsInR5cGUiOjEsImV4cCI6MTc0Nzk4MzIyMiwiY3JlYXRlZCI6MTc0NjY4NzIyMjAxMX0.pmUfTkxkbBirDMbnMR1IaLsbSiiwHc366_yyAetCzTOWYxTNgmQlmvw26_W62NHLOebB_ZAEgZsPvkJcaLOoPg'
                        },
                        success: (uploadFileRes) => {
                           const response = JSON.parse(uploadFileRes.data);
                           if (response.code === 200) {
                              resolve(response.data);
                           } else {
                              reject(new Error('上传失败'));
                           }
                        },
                        fail: (error) => {
                           reject(error);
                        }
                     });
                  });
               });
               try {
                  const uploadedUrls = await Promise.all(uploadPromises);
                  this.voiceFile = uploadedUrls.join(',');
                  console.log('this.voiceFile', this.voiceFile)
                  uni.hideLoading();
               } catch (error) {
                  uni.hideLoading();
                  uni.showToast({
                     title: '语音文件上传失败',
                     icon: 'error'
                  });
                  return;
               }
            }
            const preciseRegex = /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/;
            if (!this.time) {
               uni.showToast({
@@ -225,19 +380,8 @@
                  icon: 'none'
               })
               return
            } else if (!this.descriptionTitle) {
               uni.showToast({
                  title: '请输入问题标题',
                  icon: 'none'
               })
               return
            } else if (!this.descriptionContent) {
               uni.showToast({
                  title: '请输入问题描述',
                  icon: 'none'
               })
               return
            }
            const data = {
               time: this.time,
               problemType: this.problemType,
@@ -247,31 +391,47 @@
               latitude: this.latitude,
               longitude: this.longitude,
               detailedAddress: this.detailedAddress,
               descriptionTitle: this.descriptionTitle,
               descriptionContent: this.descriptionContent,
               images: this.images.join(','),
               videos: this.videos.join(','),
               voiceFile: this.voiceFile,
            }
            save(data).then(resp => {
               console.log(resp, '保存');
               if (resp.code == 200) {
                  uni.showToast({
                     title: '保存成功',
                     icon: 'none'
                  })
                  setTimeout(() => {
                     uni.navigateBack()
                  }, 1500)
               }
            })
            // 问题上报
            if (type == 1) {
               uni.navigateTo({
                  url: `/pages/problemReporting/problemReporting?data=${JSON.stringify(data)}`
               })
               return
            }
            // 办理结果录入
            if (type == 2) {
               uni.navigateTo({
                  url: `/pages/result-entry/index?data=${JSON.stringify(data)}`
               })
               return
            }
            // 添加
            if (type == 3) {
               save(data).then(resp => {
                  if (resp.code == 200) {
                     uni.showToast({
                        title: '保存成功',
                        icon: 'none'
                     })
                     setTimeout(() => {
                        uni.navigateBack()
                     }, 1500)
                  }
               })
            }
         },
         confirmone(e) {
            console.log(e, 'eeee');
            this.time = dayjs(e.value).format('YYYY-MM-DD')
            this.showDate = false
         },
         confirmtwo(e) {
            console.log(e, 'eeee');
            this.problemType = e.value[0]
            this.showList = false
         },
@@ -284,7 +444,7 @@
            this.showList = false
         },
         goTopagelocation() {
            console.log('0000000000000000');
            uni.navigateTo({
               url: '/pages/location/location'
            })
@@ -295,17 +455,18 @@
               sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
               sourceType: ['album'], //从相册选择
               success: (res) => {
                  console.log(res, 'res');
                  uni.showLoading()
                  console.log('res.tempFilePaths[0]', res.tempFilePaths[0])
                  uni.uploadFile({
                     url: 'https://huacheng.psciio.com/api/huacheng-communitybackstage/communitypartybuilding/uploadimage',
                     url: config.imageUrl,
                     filePath: res.tempFilePaths[0],
                     name: 'file',
                     header: {
                        'Authorization': 'Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOjE2NzYwOTg3NzQ0OTk0NjMxNjgsInR5cGUiOjMsImV4cCI6MTc0MTY4NjQ0OSwiY3JlYXRlZCI6MTc0MDM5MDQ0OTYxN30.UpanrjmCLuKlxm32IbBldBOSJJNYL8ZDrbZQM9z_HCW8X9cL8Ox8jwgX0j4_2nq3ALjYD7aPQWbVmMb2vHIIdA'
                        'Authorization': uni.getStorageSync('token')
                     },
                     success: (uploadFileRes) => {
                        console.log(JSON.parse(uploadFileRes.data), 'uploadFileRes');
                        this.images = [...this.images, JSON.parse(uploadFileRes.data).data]
                        uni.hideLoading()
                     },
@@ -325,17 +486,25 @@
               count: 1, //默认9
               sourceType: ['camera', 'album'],
               success: (res) => {
                  console.log(res, 'res');
                  const videoExtensions = /\.(mp4|avi|rmvb)$/i;
                  if (!videoExtensions.test(res.name)) {
                     uni.showToast({
                        title: '请上传mp4, avi, rmvb格式的视频',
                        icon: 'none',
                        duration: 3000
                     })
                     return
                  }
                  uni.showLoading()
                  uni.uploadFile({
                     url: 'https://huacheng.psciio.com/api/huacheng-communitybackstage/communitypartybuilding/uploadimage',
                     url: config.imageUrl,
                     filePath: res.tempFilePath,
                     name: 'file',
                     header: {
                        'Authorization': 'Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOjE2NzYwOTg3NzQ0OTk0NjMxNjgsInR5cGUiOjMsImV4cCI6MTc0MTY4NjQ0OSwiY3JlYXRlZCI6MTc0MDM5MDQ0OTYxN30.UpanrjmCLuKlxm32IbBldBOSJJNYL8ZDrbZQM9z_HCW8X9cL8Ox8jwgX0j4_2nq3ALjYD7aPQWbVmMb2vHIIdA'
                        'Authorization': uni.getStorageSync('token')
                     },
                     success: (uploadFileRes) => {
                        console.log(JSON.parse(uploadFileRes.data).data, 'uploadFileRes');
                        this.videos = [...this.videos, JSON.parse(uploadFileRes.data).data]
                        uni.hideLoading()
                     },
@@ -355,6 +524,20 @@
</script>
<style lang="scss" scoped>
   .min-108 {
      min-height: 108rpx;
   }
   .red {
      color: rgba(255, 73, 72, 1);
   }
   .pink {
      background: #FFF1F4;
      border-radius: 8rpx;
      margin-top: 19rpx;
   }
   .card {
      border-bottom: 2rpx solid rgba(0, 10, 26, 0.07);
   }
@@ -364,7 +547,7 @@
   }
   .content {
      padding: 38rpx 31rpx 62rpx 31rpx;
      padding: 38rpx 31rpx 162rpx 31rpx;
      .main {
         padding: 0 27rpx 48rpx 27rpx;
@@ -391,20 +574,6 @@
      }
   }
   .btn {
      width: 688rpx;
      height: 96rpx;
      background: linear-gradient(270deg, #FC8D55 0%, #FF4948 100%);
      border-radius: 48rpx;
      font-weight: 600;
      font-size: 35rpx;
      color: #FFFFFF;
      display: flex;
      align-items: center;
      justify-content: center;
      margin-top: 38rpx
   }
   /deep/.u-popup__content {
      border-radius: 16rpx 16rpx 0rpx 0rpx;
   }
@@ -424,4 +593,38 @@
      font-size: 30rpx;
      color: #FF4948 !important;
   }
   .footer {
      position: fixed;
      bottom: 0;
      left: 0;
      box-shadow: 0rpx -4rpx 27rpx 0rpx rgba(0, 0, 0, 0.08);
      width: calc(100% - 20rpx);
      background-color: #fff;
      display: flex;
      gap: 27rpx;
      padding: 33rpx 10rpx;
      .cancel {
         width: 331rpx;
         height: 77rpx;
         border: 2rpx solid rgba(252, 141, 85, 1);
         border-radius: 38rpx;
         display: flex;
         align-items: center;
         justify-content: center;
         color: #FF4948;
      }
      .ok {
         width: 331rpx;
         height: 77rpx;
         background: linear-gradient(270deg, #FC8D55 0%, #FF4948 100%);
         border-radius: 48rpx;
         display: flex;
         align-items: center;
         justify-content: center;
         color: #FFFFFF;
      }
   }
</style>