沙盘演示系统应用的微信小程序
pages/feedback/feedback.js
@@ -1,57 +1,152 @@
const audio = wx.createInnerAudioContext()
const recorderManager = wx.getRecorderManager()
const {
  get,
  post
} = require('../../api/request.js');
const {
  BASEURL
} = require('../../api/config')
const app = getApp()
Page({
  data: {
    isRefreshing: false,
    currentTab: 0,
    recordingSrc: '',
    isRecording: false,
    isshowVoiceMask: true, //是否显示录音中
    voiceTime: 2, //录音时长
    isshowVoiceMask: false, //是否显示录音中
    isShowVoiceView: false,
    voiceTime: 0, //录音时长
    maxVoiceTime: 60, //最长录音时间
    contDownTime: 0,
    line2Opcity: 1,
    line3Opcity: 1,
    gridConfig: {
      column: 3,
      width: 160,
      height: 160,
    },
    originFiles: [{
        url: 'https://tdesign.gtimg.com/mobile/demos/example4.png',
        name: 'uploaded1.png',
        type: 'image',
      },
      {
        url: 'https://tdesign.gtimg.com/mobile/demos/example6.png',
        name: 'uploaded2.png',
        type: 'image',
      }
    ]
    originFiles: [],
    contentValue: '', //反馈详情
    accSavePath: [], //上传的音频文件接口返回的地址
    photoSavePath: [], //上传的照片文件返回的地址
    phoneNumber: "",
    lat: "",
    lng: "",
    loading: false,
    hasMore: true,
    pageCurr: 1,
    pageSize: 20,
    listData: [], //已提问题列表
  },
  onLoad() {
    this.recorderManager = wx.getRecorderManager();
    this.recorderManager.onStart(() => {
      console.log('recorder start');
      this.setData({
        isRecording: true
      });
      this.startWaveformDrawing();
    wx.getSetting({
      success: (res) => {
        if (!res.authSetting['scope.record']) {
          // 如果用户没有授权录音权限,发起授权窗口
          wx.authorize({
            scope: 'scope.record',
            success() {
              // 用户已经同意小程序使用录音功能,可以继续操作
              console.log('用户已授权录音');
            },
            fail() {
              // 用户拒绝授权,可以给出提示或再次发起授权窗口
              console.log('用户拒绝了授权录音');
            }
          });
        } else {
          // 用户已经授权录音,可以直接进行录音操作
          console.log('用户已授权录音');
        }
      }
    });
    var that = this;
    recorderManager.onStop((res) => {
      console.log('录音停止', voiceTime);
      const voiceTime = Math.floor(res.duration / 1000)
      if (voiceTime < 2) {
        this.setData({
          isShowVoiceMask: false,
          contDownTime: this.data.maxVoiceTime,
          isShowVoiceView: false
        })
        wx.showToast({
          title: '录音时间过短',
          icon: 'error',
          time: 3000
        })
      } else {
    this.recorderManager.onStop((res) => {
      console.log('recorder stop', res);
      const {
        tempFilePath
      } = res;
      this.setData({
        recordingSrc: tempFilePath,
        isRecording: false
      });
      this.stopWaveformDrawing();
        that.setData({
          voiceTime: voiceTime,
          isShowVoiceMask: false,
          contDownTime: this.data.maxVoiceTime,
          isShowVoiceView: true
        })
        console.log('res', res);
        const {
          tempFilePath
        } = res; //这里松开按钮 会返回录音本地路径
        audio.src = tempFilePath
        console.log(tempFilePath);
        that.upACC(tempFilePath);
      }
    });
    this.recorderManager.onError((res) => {
      console.error(res);
      this.setData({
        isRecording: false
      });
      this.stopWaveformDrawing();
    recorderManager.onStart(() => {
      console.log('录音开始');
    });
    recorderManager.onError((err) => {
      console.log('录音错误', err);
    });
    wx.getLocation({
      type: 'wgs84', // 返回可以用于 `wx.openLocation` 的经纬度
      success: (res) => {
        console.log('获取位置成功', res);
        this.setData({
          lat: res.latitude,
          lng: res.longitude,
        });
      },
      fail: function (err) {
        console.error('获取位置失败', err);
      }
    });
  },
  onReady() {
    this.getList();
  },
  //上传音频文件
  upACC(tempFilePath) {
    //上传录制的音频到服务器
    wx.uploadFile({
      url: BASEURL + "wx/webFile/upPhone", //接口地址
      name: 'file', //上传文件名
      filePath: tempFilePath,
      header: {
        'tag': app.globalData.tag,
        'appId': app.globalData.AppID,
      },
      success: (res) => { //后台返回给前端识别后的文字
        console.log('录音上传成功', res);
        let jsonData = JSON.parse(res.data)
        let audioObj = {
          webPath: jsonData.content.webPath,
          id: jsonData.content.id
        };
        this.setData({
          accSavePath: [audioObj]
        })
      },
      fail: (err) => {
        // 处理上传失败的逻辑
        console.log('录音上传失败', err);
      }
    })
  },
  //删除图片
  handleRemove(e) {
    console.log("handleRemove");
    const {
@@ -60,13 +155,28 @@
    const {
      originFiles
    } = this.data;
    let imgPath = e.detail.file.url;
    const updatedFiles = this.data.originFiles.map((file) => {
      //当上传失败点击时重新上传
      if (file.url === imgPath && file.uploadTask) {
        file.uploadTask.abort();
      }
    });
    originFiles.splice(index, 1);
    this.setData({
      originFiles,
      originFiles: originFiles,
    });
  },
  handleClick() {
  handleClick(e) {
    console.log("handleClick");
    let imgPath = e.detail.file.url;
    const updatedFiles = this.data.originFiles.map((file) => {
      //当上传失败点击时重新上传
      if (file.url === imgPath && file.status === "reload") {
        this.onUploadPhoto(imgPath);
      }
    });
  },
  handleAdd(e) {
    console.log("handleAdd");
@@ -76,159 +186,409 @@
    const {
      originFiles
    } = this.data;
    this.setData({
      originFiles: [...originFiles, ...files], // 此时设置了 fileList 之后才会展示选择的图片
    const updatedList = files.map(item => {
      return {
        ...item,
        status: 'loading',
        uploadTask: this.onUploadPhoto(item.url)
      }; // 保留所有其他字段,并添加 displayText 字段
    });
    // 更新列表数据
    this.setData({
      originFiles: [...originFiles, ...updatedList], // 此时设置了 fileList 之后才会展示选择的图片
    });
  },
  handleSuccess(e) {
  },
  /**
   * 上传图片
   */
  onUpload() {
    wx.uploadFile({
      url: 'https://example.weixin.qq.com/upload', // 仅为示例,非真实的接口地址
      filePath: file.url,
  onUploadPhoto(imgPath) {
    const uploadTask = wx.uploadFile({
      url: BASEURL + "wx/webFile/upPhoto", // 仅为示例,非真实的接口地址
      filePath: imgPath,
      name: 'file',
      formData: {
        user: 'test'
      header: {
        'tag': app.globalData.tag,
        'appId': app.globalData.AppID,
      },
      success: () => {
        this.setData({
          [`fileList[${length}].status`]: 'done',
      success: (res) => {
        console.log('图片上传成功', res);
        let jsonData = JSON.parse(res.data)
        // 更新图片上传成功状态
        const updatedFiles = this.data.originFiles.map((file) => {
          console.log('图片上传成功》》updatedFiles', file + "++++++++++" + imgPath);
          if (file.url === imgPath) {
            return {
              ...file,
              status: undefined, // 上传成功状态
              uploadTask: undefined, // 清理上传任务
              webPath: jsonData.content.webPath,
              id: jsonData.content.id
            };
          }
          return file;
        });
        // 将创建的对象添加到images数组中
        this.setData({
          originFiles: updatedFiles,
        })
      },
      fail: (err) => {
        // 处理上传失败的逻辑
        const updatedFiles = this.data.originFiles.map((file) => {
          if (file.url === imgPath) {
            return {
              ...file,
              percent: progress,
              status: "reload", // 上传失败状态
            };
          }
          return file;
        });
        this.setData({
          originFiles: updatedFiles,
        });
      }
    });
    if (uploadTask) {
      uploadTask.onProgressUpdate((res) => {
        //处理
        const progress = Math.round((res.progress / 100) * 100)
        const updatedFiles = this.data.originFiles.map((file) => {
          if (file.url === imgPath) {
            return {
              ...file,
              percent: progress,
              status: progress < 100 ? 'loading' : undefined, // 更新状态
              uploadTask: progress < 100 ? file.uploadTask : undefined, // 保持或删除uploadTask
            };
          }
          return file;
        });
        this.setData({
          originFiles: updatedFiles,
        });
      });
    }
    return uploadTask;
  },
  //按住按钮
  startHandel () {
  startHandel() {
    this.setData({
     isShowVoiceMask:true
      isShowVoiceMask: true,
      contDownTime: this.data.maxVoiceTime,
      voiceTime: 0,
      isShowVoiceView: false
    })
    console.log("开始录音")
    wx.getRecorderManager().start({
     duration: 0
    recorderManager.start({
      duration: 0
    })
   },
   //松开按钮
   endHandle () {
    this.setData({
     isShowVoiceMask:false
    })
    this.startRecordingCountdown();
  },
  //松开按钮
  endHandle() {
    this.stopRecordingCountdown();
    console.log("结束")
    const recorderManager = wx.getRecorderManager()
    //录音停止函数
    var that = this;
    wx.getRecorderManager().onStop((res) => {
      const voiceTime =  Math.floor(res.duration/1000)
      console.log('voiceTime',voiceTime);
      that.setData({
        voiceTime
      })
      console.log('res',res);
     const { tempFilePath } = res; //这里松开按钮 会返回录音本地路径
     audio.src = tempFilePath
     console.log(tempFilePath);
     //上传录制的音频到服务器
     // wx.uploadFile({
     //  url: '接口地址' + api.voice, //接口地址
     //  name: 'file', //上传文件名
     //  filePath: tempFilePath,
     //  success: function (res) { //后台返回给前端识别后的文字
     //   var model = res.data
     //   var modeljson = JSON.parse(model)
     //   if (modeljson.status_code == 500) {
     //    wx.showToast({
     //     title: '语音转换失败',
     //     image: '/assets/image/icon/fail@2x.png'
     //    })
     //    return false;
     //   }
     //   if (modeljson.meta.status_code === 200 && !modeljson.data.err_msg) {
     //    var saymessage = modeljson.data.message;
     //    wx.setStorageSync('sayinfo', saymessage)
     //    that.setData({
     //     inpvalue: saymessage
     //    })
     //    setTimeout(() =>{
     //     wx.navigateTo({
     //      url: '../loding/loding'
     //     })
     //    },2000)
     //    setTimeout(() => {
     //     wx.hideLoading();
     //    }, 100)
     //   } else if (modeljson.data.err_msg) {
     //    wx.showToast({
     //     title: '请大声说话',
     //     image: '/assets/image/icon/fail@2x.png'
     //    })
     //    return false;
     //   }
     //  }
     // })
    })
    //触发录音停止
    wx.getRecorderManager().stop()
   },
// 播放
handlePlay(e){
  // 倒计时
  let time = this.data.voiceTime
  audio.play()
  let timer1 = -1,timer2 = -1,timer3 = -1,timer4 = -1,timer5 = -1,timer6 = -1;
  // 第一次播放为0 第二次播放2秒钟
  timer6 = setInterval(()=>{
    console.log('时间',time);
    if(time <= 0){
      this.setData({
        line2Opcity: 1,
        line3Opcity: 1
      })
      clearInterval(timer6)
      clearTimeout(timer2)
      clearTimeout(timer3)
      clearTimeout(timer4)
      clearTimeout(timer5)
      return
    }
    timer2 = setTimeout(()=>{
      console.log('timer2');
      this.setData({
        line2Opcity: 0,
        line3Opcity: 0
      })
    },300)
    timer3 = setTimeout(()=>{
      console.log('timer3');
        this.setData({
          line2Opcity: 1,
          line3Opcity:0
        })
    },600)
    timer4 = setTimeout(()=>{
      console.log('timer4');
    recorderManager.stop()
  },
  // 播放
  handlePlay(e) {
    // 倒计时
    let time = this.data.voiceTime
    audio.play()
    let timer1 = -1,
      timer2 = -1,
      timer3 = -1,
      timer4 = -1,
      timer5 = -1,
      timer6 = -1;
    // 第一次播放为0 第二次播放2秒钟
    timer6 = setInterval(() => {
      console.log('时间', time);
      if (time <= 0) {
        this.setData({
          line2Opcity: 1,
          line3Opcity: 1
      })
    },900)
    timer5 = setTimeout(()=>{
      console.log('timer5');
        })
        clearInterval(timer6)
        clearTimeout(timer2)
        clearTimeout(timer3)
        clearTimeout(timer4)
        clearTimeout(timer5)
        return
      }
      timer2 = setTimeout(() => {
        console.log('timer2');
        this.setData({
          line2Opcity: 0,
          line3Opcity: 0
        })
    },1200)
  },1200)
  // 倒计时
  timer1 = setInterval(()=>{
    time--;
    if(time <= 0){
      clearInterval(timer1)
      return
    }
},1000)
      }, 200)
      timer3 = setTimeout(() => {
        console.log('timer3');
        this.setData({
          line2Opcity: 1,
          line3Opcity: 0
        })
      }, 400)
      timer4 = setTimeout(() => {
        console.log('timer4');
        this.setData({
          line2Opcity: 1,
          line3Opcity: 1
        })
      }, 600)
      timer5 = setTimeout(() => {
        console.log('timer5');
        this.setData({
          line2Opcity: 0,
          line3Opcity: 0
        })
      }, 800)
    }, 800)
    // 倒计时
    timer1 = setInterval(() => {
      time--;
      if (time <= 0) {
        clearInterval(timer1)
        return
      }
    }, 1000)
}
  },
  //开启定时器
  startRecordingCountdown() {
    console.log("startRecordingCountdown");
    const that = this;
    if (this.recordingInterval) {
      // 如果定时器已经在运行,避免重复启动
      return;
    }
    this.recordingInterval = setInterval(() => {
      const newVoiceTime = that.data.voiceTime + 1;
      const newContDownTime = that.data.contDownTime - 1;
      that.setData({
        voiceTime: newVoiceTime,
        contDownTime: newContDownTime
      });
      if (this.data.voiceTime >= this.data.maxVoiceTime) {
        that.stopRecordingCountdown();
        that.endHandle();
      }
    }, 1000);
  },
  onUnload() {
    if (this.recordingInterval) {
      clearInterval(this.recordingInterval);
      this.recordingInterval = null;
    }
  },
  stopRecordingCountdown() {
    console.log("stopRecordingCountdown");
    if (this.recordingInterval) {
      clearInterval(this.recordingInterval);
      this.recordingInterval = null;
      console.log("Recording countdown stopped");
    }
  }, // 切换 Tabs
  switchTab: function (e) {
    const tab = parseInt(e.currentTarget.dataset.tab);
    this.setData({
      currentTab: tab
    });
  },
  onPullDownRefresh() {
    this.getList(true);
  },
  //上传问题
  feelBackPost() {
    wx.showLoading({
      title: '正在提交...', // 加载提示文字
      mask: true // 是否显示透明蒙层,防止触摸穿透,默认为 false
    });
    this.data.originFiles.map((file) => {
      let imageObj = {
        webPath: file.webPath,
        id: file.id
      };
      this.setData({
        photoSavePath: [...this.data.photoSavePath, imageObj]
      })
    })
    const app = getApp();
    const data = {
      images: this.data.photoSavePath,
      audios: this.data.accSavePath,
      content: this.data.contentValue,
      lng: this.data.lng,
      lat: this.data.lat,
      clientId: app.globalData.clientId,
      phone: this.data.phoneNumber
    };
    post({
      url: "wx/issue/addIssueReport",
      data: data
    }).then(response => {
      // 处理成功响应
      console.log('请求成功:', response);
      // 加载完成后隐藏加载动画
      wx.hideLoading();
      //完成后回到首页
      wx.showToast({
        title: '提交成功',
        icon: 'success',
        duration: 2000,
        success() {}
      })
      setTimeout(() => {
        wx.navigateBack({
          delta: 1
        });
      }, 2000);
    }).catch(error => {
      // 加载完成后隐藏加载动画
      wx.hideLoading();
      // 处理错误响应
      console.error('请求失败:', error);
      this.setData({
        showErrorDialog: true,
        errorData: error.msg
      })
      // }
    });
  },
  handleDelete() {
    this.setData({
      isShowVoiceView: false,
      voiceTime: 0,
    })
  },
  //提交
  submit() {
    if (this.data.contentValue !== "" || this.data.photoSavePath.length > 0 || this.data.accSavePath !== "") {
      if (this.data.phoneNumber !== "" && this.data.phoneNumber.length !== 11) {
        wx.showToast({
          title: '联系电话错误',
          icon: 'error',
          duration: 2000,
          success() {}
        })
      } else {
        this.feelBackPost();
      }
    } else {
      wx.showToast({
        title: '请输入一项反馈内容',
        icon: 'error',
        duration: 2000,
        success() {}
      })
    }
  },
  //监听手机号的输入
  phoneInput(e) {
    this.setData({
      phoneNumber: e.detail.value
    });
  },
  //监听
  contentInput(e) {
    this.setData({
      contentValue: e.detail.value
    });
  },
  //获取已提问题列表
  getList(isRefresh) {
    if (isRefresh) {
      this.setData({
        isRefreshing: false,
        pageCurr: 1,
        listData: []
      });
    }
    const app = getApp();
    const params = {
      url: 'wx/issue/getIssueReports',
      data: {
        clientId: app.globalData.clientId
      }
    };
    get(params).then(data => {
      const updatedList = data.content.obj.map(item => {
        if (item.replyTime === "" || item.replyTime === null) {
          item.replyTime = "未回复"
        }
        return item;
      });
      this.setData({
        listData: [...this.data.listData, ...updatedList],
        isRefreshing: false, // 将triggered属性设置为false,表示下拉刷新已完成
        isWXRefreshing: false, // 将triggered属性设置为false,表示下拉刷新已完成
        loading: false,
        hasMore: this.data.pageCurr < data.content.pageTotal
      })
      this.updateDisplayText();
    }).catch(err => {
      // 错误回调
      this.setData({
        isRefreshing: false, // 将triggered属性设置为false,表示下拉刷新已完成
        isWXRefreshing: false, // 将triggered属性设置为false,表示下拉刷新已完成
        loading: false
      })
      wx.showToast({
        title: err.msg,
        icon: 'error',
        duration: 3000
      })
    });
  },
  //加载更多
  loadMore() {
    if (this.data.hasMore && !this.data.loading) {
      this.setData({
        loading: true,
        pageCurr: this.data.pageCurr + 1
      })
      this.getList();
    }
  },
  onDelete(e) {
    const item = e.currentTarget.dataset.item;
    const that = this;
    wx.showLoading({
      title: '正在删除请稍候...', // 加载提示文字
      mask: true // 是否显示透明蒙层,防止触摸穿透,默认为 false
    });
    const data = {
      issueReportId: item.issueReportId, //取水口ID
      clientId: app.globalData.clientId, //阀控器地址
    };
    post({
      url: "wx/issue/deleteIssueReport",
      data: data,
      timeout: 180000
    }).then(response => {
      // 处理成功响应
      console.log('请求成功:', response);
      // 加载完成后隐藏加载动画
      wx.hideLoading();
      //重新获取列表刷新数据
      this.getList(true);
    }).catch(error => {
      // 加载完成后隐藏加载动画
      wx.hideLoading();
      // 处理错误响应
      console.error('请求失败:', error);
    });
  }
});