沙盘演示系统应用的微信小程序
zuoxiao
2024-10-18 35cd1fc2e97ee8c8ec93d632cfc6b8b90e7a6e2b
1.首页添加横滑删除功能2.同步最新代码
20个文件已修改
1个文件已添加
1017 ■■■■■ 已修改文件
api/config.js 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app.js 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app.json 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
images/delete.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
images/question.svg 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/feedback/feedback.js 424 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/feedback/feedback.wxml 87 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/feedback/feedback.wxss 121 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/home/home.js 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/home/home.json 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/home/home.wxml 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/home/home.wxss 51 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/openCard/openCard.js 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/openCard/openCard.wxml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/openCard/openCard.wxss 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/rechargeCard/rechargeCard.js 183 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/rechargeCard/rechargeCard.wxml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/valveList/valveList.js 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/valveList/valveList.wxml 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/waterIntake/waterIntake.js 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/waterIntake/waterIntake.wxss 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/config.js
@@ -8,7 +8,8 @@
  case 'test':
    // BASEURL = 'https://irrigate.dayuyanjiuyuan.top/'
    // BASEURL = 'https://d4x9787456.vicp.fun/'
    BASEURL = 'http://127.0.0.1:8087/'
    // BASEURL = 'http://127.0.0.1:8087/'
    BASEURL = 'http://192.168.40.166:8087/'
    break
  default:
    BASEURL = ''
app.js
@@ -14,9 +14,9 @@
    })
  },
  globalData: {
    sessionId:'2024071616542300009',
    clientId:'2024062716083600006',
    tag:'test',
    sessionId:'2024052821300200006',
    clientId:'2024091215314000006',
    tag:'ym',
    userInfo: null,
    userId:"",
    userCode:"",
app.json
@@ -23,8 +23,7 @@
    "navigationBarBackgroundColor": "#1890FF"
  },
  "componentFramework": "glass-easel",
  "sitemapLocation": "sitemap.json",
  "lazyCodeLoading": "requiredComponents"
  "sitemapLocation": "sitemap.json"
}
images/delete.svg
New file
@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="24" cy="24" r="20" fill="none" stroke="#1890FF" stroke-width="4"/><path d="M17 31L31 17" stroke="#1890FF" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M19 19L17 17" stroke="#1890FF" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M31 31L29 29" stroke="#1890FF" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/></svg>
images/question.svg
@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="70.80000305175781" height="75.00926971435547" viewBox="0 0 70.80000305175781 75.00926971435547"><g><path d="M32.3,0.00927001C34.05,0.00927001,35.4,1.40927,35.4,3.10927C35.4,4.80927,34,6.20927,32.3,6.20927L12.15,6.20927C8.85,6.40927,6.25,9.15927,6.25,12.4593L6.25,62.8093C6.45,66.1093,9.2,68.7093,12.5,68.7093L58.7,68.7093C62,68.5093,64.6,65.7593,64.6,62.4593L64.6,28.1093C64.6,26.3593,66,25.0093,67.7,25.0093C69.45,25.0093,70.8,26.4093,70.8,28.1093L70.8,62.5093C70.8,69.4093,65.2,75.0093,58.3,75.0093L12.5,75.0093C5.6,75.0093,0,69.4093,0,62.5093L0,12.5093C0,5.60927,5.6,0.00927001,12.5,0.00927001L32.3,0.00927001ZM42.7,52.1093C44.45,52.1093,45.8,53.5093,45.8,55.2093C45.8,56.9593,44.4,58.3093,42.7,58.3093L19.8,58.3093C18.05,58.3093,16.7,56.9093,16.7,55.2093C16.7,53.4593,18.1,52.1093,19.8,52.1093L42.7,52.1093ZM30.2,37.5093C31.95,37.5093,33.3,38.9093,33.3,40.6093C33.3,42.3093,31.9,43.7093,30.2,43.7093L19.8,43.7093C18.05,43.7093,16.7,42.3093,16.7,40.6093C16.7,38.9093,18.1,37.5093,19.8,37.5093L30.2,37.5093ZM51.45,6.30927L61.75,12.1593L49.9,32.4593L43.2,35.2593C42.2,35.7093,41.05,35.2093,40.6,34.2093C40.55,34.0593,40.5,33.8593,40.45,33.6593L39.6,26.5593L51.45,6.30927ZM61.6,0.809269C64.4,2.35927,65.4,5.90927,63.85,8.70927C63.85,8.75927,63.8,8.75927,63.8,8.80927L62.8,10.5093L52.5,4.65927L53.5,2.95927C55.1,0.109269,58.75,-0.840731,61.6,0.809269Z" fill="#4090FF" fill-opacity="1"/></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="60.80000305175781" height="65.00926971435547" viewBox="0 0 70.80000305175781 75.00926971435547"><g><path d="M32.3,0.00927001C34.05,0.00927001,35.4,1.40927,35.4,3.10927C35.4,4.80927,34,6.20927,32.3,6.20927L12.15,6.20927C8.85,6.40927,6.25,9.15927,6.25,12.4593L6.25,62.8093C6.45,66.1093,9.2,68.7093,12.5,68.7093L58.7,68.7093C62,68.5093,64.6,65.7593,64.6,62.4593L64.6,28.1093C64.6,26.3593,66,25.0093,67.7,25.0093C69.45,25.0093,70.8,26.4093,70.8,28.1093L70.8,62.5093C70.8,69.4093,65.2,75.0093,58.3,75.0093L12.5,75.0093C5.6,75.0093,0,69.4093,0,62.5093L0,12.5093C0,5.60927,5.6,0.00927001,12.5,0.00927001L32.3,0.00927001ZM42.7,52.1093C44.45,52.1093,45.8,53.5093,45.8,55.2093C45.8,56.9593,44.4,58.3093,42.7,58.3093L19.8,58.3093C18.05,58.3093,16.7,56.9093,16.7,55.2093C16.7,53.4593,18.1,52.1093,19.8,52.1093L42.7,52.1093ZM30.2,37.5093C31.95,37.5093,33.3,38.9093,33.3,40.6093C33.3,42.3093,31.9,43.7093,30.2,43.7093L19.8,43.7093C18.05,43.7093,16.7,42.3093,16.7,40.6093C16.7,38.9093,18.1,37.5093,19.8,37.5093L30.2,37.5093ZM51.45,6.30927L61.75,12.1593L49.9,32.4593L43.2,35.2593C42.2,35.7093,41.05,35.2093,40.6,34.2093C40.55,34.0593,40.5,33.8593,40.45,33.6593L39.6,26.5593L51.45,6.30927ZM61.6,0.809269C64.4,2.35927,65.4,5.90927,63.85,8.70927C63.85,8.75927,63.8,8.75927,63.8,8.80927L62.8,10.5093L52.5,4.65927L53.5,2.95927C55.1,0.109269,58.75,-0.840731,61.6,0.809269Z" fill="#4090FF" fill-opacity="1"/></g></svg>
pages/feedback/feedback.js
@@ -1,55 +1,130 @@
const audio = wx.createInnerAudioContext()
const recorderManager = wx.getRecorderManager()
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: [
    ],
    feedBackList: Array(19).fill({
      createTime: "2023-05-06 12:36:25",
      responseTime: "2023-05-07 12:36:25"
    }),
    contentValue:''//反馈详情
  },
  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 {
        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);
      }
    this.recorderManager.onStop((res) => {
      console.log('recorder stop', res);
      const {
        tempFilePath
      } = res;
      this.setData({
        recordingSrc: tempFilePath,
        isRecording: false
      });
      this.stopWaveformDrawing();
      //上传录制的音频到服务器
      // 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;
      //   }
      //  }
      // })
    });
    this.recorderManager.onError((res) => {
      console.error(res);
      this.setData({
        isRecording: false
      });
      this.stopWaveformDrawing();
    recorderManager.onStart(() => {
      console.log('录音开始');
    });
    recorderManager.onError((err) => {
      console.log('录音错误', err);
    });
  },
  handleRemove(e) {
@@ -99,136 +174,177 @@
    });
  },
  //按住按钮
  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;
    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);
  },
  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.setData({
      isRefreshing: false
    });
  },
  feelBack(){
    wx.showLoading({
      title: '正在提交...', // 加载提示文字
      mask: true // 是否显示透明蒙层,防止触摸穿透,默认为 false
    });
    const app = getApp();
    const data = {
      content: this.data.contentValue, //取水口ID
      image: this.data.vcId, //虚拟卡ID
      operator: app.globalData.sessionId, //操作员
      forceOpen: !!isforce // 使用逻辑非操作符 !! 来确保 isForce 是布尔值
    };
    post({
      url: "operation/feedback/add",
      data: data
    }).then(response => {
      // 处理成功响应
      console.log('请求成功:', response);
      // 加载完成后隐藏加载动画
      wx.hideLoading();
      //完成后回到首页
      wx.reLaunch({
        url: '/pages/home/home?param=true' // 首页的路径,根据实际情况填写
      });
    }).catch(error => {
      // 加载完成后隐藏加载动画
      wx.hideLoading();
      // 处理错误响应
      console.error('请求失败:', error);
      // if (error.code === "10005") {
      //   this.setData({
      //     showDialog: false,
      //     showForceConfirm: true
      //   })
      // } else {
      this.setData({
        showErrorDialog: true,
        errorData: error.msg
      })
      // }
    });
  },
  handleDelete(){
   this.setData({
    isShowVoiceView:false,
    voiceTime:0,
   })
  }
});
pages/feedback/feedback.wxml
@@ -1,30 +1,65 @@
<view class="container">
  <view class="container-item">
    <text class="fb-text">反馈详情:</text>
    <textarea class="input-class" />
  </view>
  <view class="divider"></view>
  <view class="container-item">
    <text class="img-upload">图片(最多三张):</text>
    <t-upload style="margin-top: 20rpx;" media-type="{{['image']}}" files="{{originFiles}}" gridConfig="{{gridConfig}}" bind:success="handleSuccess" max="3" bind:add="handleAdd" bind:remove="handleRemove" bind:click="handleClick" bind:sort-end="handleSortEnd" />
  </view>
  <view class="divider"></view>
  <view class="container-voice">
    <text class="fb-text">录音:</text>
    <view class="voice_wrapper">
      <image class="voice_img" bindtouchstart='startHandel' bindtouchend='endHandle' src="/images/tape.svg" mode="" />
      <view class="voice_content" bind:tap="handlePlay" wx:if="{{voiceTime}}">
        <view class="left">
          <view class="line"></view>
          <view class="line" style="opacity:{{line2Opcity}}" id="test2"></view>
          <view class="line" style="opacity:{{line3Opcity}}" id="test3"></view>
        </view>
        <view class="right">{{voiceTime}}"</view>
      </view>
  <!-- 顶部 Tabs -->
  <view class="tabs">
    <view class="tab" bindtap="switchTab" data-tab="0" id="tab0">
      问题反馈
      <view class="indicator" wx:if="{{currentTab === 0}}"></view>
    </view>
    <view class="tab" bindtap="switchTab" data-tab="1" id="tab1">
      已提问题
      <view class="indicator" wx:if="{{currentTab === 1}}"></view>
    </view>
  </view>
  <!-- 录音中 -->
  <view wx:if="{{isShowVoiceMask}}" class="voice_starting">录音中</view>
  <button class="fb-submit">提交</button>
  <view class="container-feedBack" wx:if="{{currentTab === 0}}">
    <view class="container-item">
      <text class="fb-text">反馈详情:</text>
      <textarea class="input-class"  value="{{contentValue}}"  />
    </view>
    <view class="divider"></view>
    <view class="container-item">
      <text class="fb-text">图片(最多三张):</text>
      <t-upload style="margin-top: 20rpx;" media-type="{{['image']}}" files="{{originFiles}}" gridConfig="{{gridConfig}}" bind:success="handleSuccess" max="3" bind:add="handleAdd" bind:remove="handleRemove" bind:click="handleClick" bind:sort-end="handleSortEnd" />
    </view>
    <view class="divider"></view>
    <view class="container-voice">
      <text class="fb-text">录音:</text>
      <view class="voice_wrapper">
        <image class="voice_img" bindtouchstart='startHandel' bindtouchend='endHandle' src="/images/tape.svg" mode="" />
        <view class="voice_content" bind:tap="handlePlay" wx:if="{{isShowVoiceView}}">
          <view class="left">
            <view class="line"></view>
            <view class="line" style="opacity:{{line2Opcity}}" id="test2"></view>
            <view class="line" style="opacity:{{line3Opcity}}" id="test3"></view>
          </view>
          <view class="right">{{voiceTime}}"</view>
        </view>
        <view class="voice_delete"  bind:tap="handleDelete" wx:if="{{isShowVoiceView}}" ><image src="/images/delete.svg"/></view>
      </view>
    </view>
    <!-- 录音中 -->
    <view wx:if="{{isShowVoiceMask}}" class="voice_starting">录音中{{contDownTime}}秒</view>
    <button class="fb-submit">提交</button>
  </view>
  <scroll-view class="container-scroll" wx:if="{{currentTab === 1}}" scroll-y="true" refresher-enabled="true" refresher-threshold="50" bindrefresherrefresh="onPullDownRefresh" refresher-triggered="{{isRefreshing}}">
    <block wx:for="{{feedBackList}}" wx:key="index">
      <view class="item">
        <view class="item-data">
          <text>提问时间:</text>
          <text>{{item.createTime}}</text>
        </view>
        <view class="item-data">
          <text>响应时间:</text>
          <text>{{item.responseTime}}</text>
        </view>
      </view>
    </block>
    <view wx:if="{{feedBackList.length === 0}}" class="noMore-View">
      <image class="noMore-img" src="/images/no_more.svg" />
      <text class="noMore-text">没有数据</text>
    </view>
  </scroll-view>
</view>
pages/feedback/feedback.wxss
@@ -2,15 +2,37 @@
.container {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100vh;
  padding-left: 30rpx;
  padding-right: 30rpx;
  width: calc(100% - 0rpx);
  /* 考虑了左右边距后的实际宽度 */
  background-color: #fff;
  justify-content: flex-start;
  justify-content: center;
  align-items: center;
}
.container-scroll{
  flex: 1;
  overflow-y: auto;
  z-index: 0;
  display: flex;
  flex-direction: column;
  padding-bottom: 20rpx; /* 增加底部填充 */
}
.container-feedBack {
  width: calc(100% - 80rpx);
  /* 40rpx 为左右 padding 的总和 */
  height: 100vh;
  /* 考虑了左右边距后的实际宽度 */
  background-color: #fff;
  padding-left: 40rpx;
  padding-right: 40rpx;
  padding-top: 1rpx;
  padding-bottom: 1rpx;
}
.btn {
  margin: 10px;
@@ -43,9 +65,13 @@
.input-class {
  border-radius: 5px;
  border: 2rpx solid #000000;
  height: 20vh;
  height: 10vh;
  width: 100%;
  background-color: #fcfcfc;
  display: flex;
  flex-direction: column;
  padding-left: 10rpx;
  padding-top: 3rpx;
}
.img-upload {
@@ -54,23 +80,21 @@
}
.container-item {
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-start
}
.container-voice {
  width: 100%;
  display: flex;
  flex-direction: row;
  align-items: center;
}
.fb-text {
  font-size: 35rpx;
  margin-left: 30rpx;
  margin-bottom: 10rpx;
}
.fb-submit {
@@ -78,7 +102,7 @@
  background-color: #1890FF;
  font-size: 35rpx;
  color: white;
  margin-top: 50rpx;
  margin-top: 200rpx;
}
.voice_img {
@@ -116,7 +140,17 @@
  border-radius: 15rpx;
  background-color: #1890FF;
}
.voice_delete{
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-left: 16rpx;
  padding: 0 6rpx;
  box-sizing: border-box;
  width: 55rpx;
  height: 55rpx;
  border-radius: 15rpx;
}
.voice_content .left {
  display: flex;
  align-items: center;
@@ -146,17 +180,72 @@
  margin-right: 20rpx;
}
.voice_starting{
.voice_starting {
  position: fixed;
  top: 30%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 200rpx;
  height: 200rpx;
  line-height: 200rpx;
  width: 300rpx;
  height: 300rpx;
  align-items: center;
  line-height: 300rpx;
  background-color: #787879;
  color: #fff;
  text-align: center;
  border-radius: 100rpx; /* 使其呈现圆形 */
  border-radius: 150rpx;
  /* 使其呈现圆形 */
  z-index: 10000;
}
.tabs {
  display: flex;
  justify-content: space-around;
  position: relative;
  width: 100%;
  border-bottom: 1px solid #eee;
  margin-bottom: 20rpx;
  /* Tabs 占满整个横向屏幕 */
}
.tab {
  font-size: 16px;
  padding: 10px;
  cursor: pointer;
  position: relative;
  width: 50%;
  /* Tabs 平分整个横向屏幕 */
  text-align: center;
  /* 文字居中 */
}
.indicator {
  width: 100%;
  height: 3px;
  background-color: #1890FF;
  position: absolute;
  bottom: 0;
  left: 0;
  transform: translateX(0);
  /* 初始化位置 */
}
.item {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  /*表示不换行*/
  padding-left: 40rpx;
  padding-right: 40rpx;
  width: calc(100% - 80rpx);
  margin-bottom: 40rpx;
}
.item-data {
  display: flex;
  flex-direction: column;
  flex-grow: 1;
}
.item-data text {
  font-size: 30rpx;
}
pages/home/home.js
@@ -151,28 +151,34 @@
  onShareAppMessage() {
  },
  // 充值
  recharge() {
    // wx.navigateTo({
    //   url: '/pages/rechargeCard/rechargeCard',
    // })
    wx.showToast({
      title: '暂未开放',
      icon: 'none'
    wx.navigateTo({
      url: '/pages/rechargeCard/rechargeCard',
    })
    // wx.showToast({
    //   title: '暂未开放',
    //   icon: 'none'
    // })
  },
  //开关阀记录
  openValveList() {
    // wx.navigateTo({
    //   url: '/pages/valveList/valveList',
    // })
    wx.showToast({
      title: '暂未开放',
      icon: 'none'
    wx.navigateTo({
      url: '/pages/valveList/valveList',
    })
    // wx.showToast({
    //   title: '暂未开放',
    //   icon: 'none'
    // })
  },
  //问题反馈
  feedBack() {
    wx.showToast({
      title: '暂未开放',
      icon: 'none'
    // wx.showToast({
    //   title: '暂未开放',
    //   icon: 'none'
    // })
    wx.navigateTo({
      url: '/pages/feedback/feedback',
    })
  },
  handleChange(e) {
@@ -448,5 +454,8 @@
      console.log('Failed to load parameter:false');
    }
  
  },
  onDelete(){
  }
})
pages/home/home.json
@@ -3,7 +3,8 @@
  "usingComponents": {
    "t-avatar": "tdesign-miniprogram/avatar/avatar",
    "t-switch": "tdesign-miniprogram/switch/switch",
    "t-dialog": "tdesign-miniprogram/dialog/dialog"
    "t-dialog": "tdesign-miniprogram/dialog/dialog",
    "t-swipe-cell": "tdesign-miniprogram/swipe-cell/swipe-cell"
  },
  "navigationBarTitleText": "大禹节水",
  "navigationBarTextStyle": "white",
pages/home/home.wxml
@@ -9,7 +9,7 @@
        <text class="head-bottom">{{userPhone}}</text>
      </view>
      <view class="head-button-wrapper">
        <text class="unbind" bind:tap="feedBack">解绑</text>
        <text class="unbind" bind:tap="">解绑</text>
        <text class="head-bottom" bind:tap="feedBack">联系客服</text>
      </view>
      <view class="scen-view" bind:tap="scenCode">
@@ -33,7 +33,7 @@
      <image src="/images/record.svg" />
      <text>开关阀记录</text>
    </view>
    <view class="center-view" bind:tap="feedBack">
    <view class="center-view-question" bind:tap="feedBack">
      <image src="/images/question.svg" />
      <text>问题反馈</text>
    </view>
@@ -52,9 +52,12 @@
      <view class="dot"></view>
      <view class="dot"></view>
    </view>
    <view class="scroll-bg">
      <view wx:if="{{listData.length > 0}}" class="list-item" wx:for="{{listData}}" wx:key="index">
        <view class="item-left">
        <t-swipe-cell style="width: 100%;" class="swipe-cell-base">
        <view class="swipe-cell" >
           <view class="item-left">
          <!-- <image class="item-img" src="/images/pipeline.svg" /> -->
          <text>{{item.intakeNum}}</text>
          <image class="item-img" src="{{item.isOnLine ? '/images/wifi_no.svg' : '/images/wifi_off.svg'}}" />
@@ -63,8 +66,13 @@
          <!-- <t-switch  class="switch" data-item="{{item}}" bindchange="handleChange" value="{{true}}" label="{{['开', '关']}}" slot="note" /> -->
          <text class="item-button" bind:tap="handleChange" data-item="{{item}}">关阀</text>
        </view>
        </view>
        <view slot="right" class="delete-btn" bind:tap="onDelete">删除</view>
      </t-swipe-cell>
      </view>
    </view>
    <view wx:if="{{listData.length === 0}}" class="noMore-View-home">
      <image class="noMore-img" src="/images/no_more.svg" />
      <text class="noMore-text">没有开泵记录</text>
pages/home/home.wxss
@@ -101,7 +101,8 @@
  /* 使 center-wrapper 在头部之上 */
}
.center-view {
.center-view,
.center-view-question {
  flex: 1;
  /* 每个元素平分宽度 */
  display: flex;
@@ -122,8 +123,17 @@
  margin-bottom: 10rpx;
  /* 图标和文本之间的间距 */
}
.center-view text {
.center-view-question image{
  padding-top: 10rpx;
  width: 75rpx;
  /* 根据需要调整图标大小 */
  height: 75rpx;
  /* 根据需要调整图标大小 */
  margin-bottom: 15rpx;
  /* 图标和文本之间的间距 */
}
.center-view text,
.center-view-question text {
  margin-top: 15rpx;
  font-size: 30rpx;
  color: #1890FF;
@@ -151,7 +161,7 @@
  background-color: #fff;
  margin-bottom: 2rpx;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-left: 30rpx;
  padding-right: 30rpx;
@@ -222,9 +232,12 @@
  justify-content: center;
  padding-bottom: 15rpx;
}
.refresh-button:active{
  background-color: #7c7c7c; /* Change to a darker color when pressed */
.refresh-button:active {
  background-color: #7c7c7c;
  /* Change to a darker color when pressed */
}
.refresh-view {
  text-align: center;
  padding: 30rpx;
@@ -288,7 +301,7 @@
.dialog {
  --td-dialog-content-font-size: 40rpx;
  --td-dialog-content-line-height: 50rpx
  --td-dialog-content-line-height: 60rpx
}
.noMore-View-home {
@@ -317,7 +330,8 @@
}
.item-button:active {
  background-color: #7c7c7c; /* Change to a darker color when pressed */
  background-color: #7c7c7c;
  /* Change to a darker color when pressed */
}
.divider {
@@ -353,4 +367,25 @@
.scen-view text {
  font-size: 30rpx;
  color: #ffffff;
}
.delete-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 120rpx;
  height: 100%;
  color: white;
  background-color: #e34d59;
}
.swipe-cell{
  display: flex;
  justify-content: space-between; /* 使子元素在主轴上均匀分布 */
  background-color: #fff;
  margin-bottom: 2rpx;
  width: 100wh;
}
.swipe-cell-base{
}
pages/openCard/openCard.js
@@ -14,7 +14,8 @@
    vcId: "",
    activeIndex: -1,
    datetimeVisible: false,
    datetime: new Date().getTime(),
    dateStartTime: new Date().getTime(),
    dateEndTime: new Date().getTime() + 24 * 60 * 60 * 1000,
    datetimeText: '',
    allCardPoints: [], // 所有虚拟卡
    irrigateProfile: [], //获取所选灌溉方式的详细数据
@@ -36,7 +37,8 @@
    radioValue: "0", //开阀方式选中的类型
    costiomTime: "", //自定义灌溉时间
    waterAmount: 0, //定量开阀的水量
    costiomWater:"",//输入的自定义水量
    costiomWater: "", //输入的自定义水量
    isWXRefreshing:false,
  },
  openValva(event) {
    const {
@@ -51,7 +53,7 @@
      // 选择虚拟卡后
      this.initDialogData();
      this.setData({
        vcId: item.vcId,
        vcId: item.id,
      })
    }
  },
@@ -103,7 +105,10 @@
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {
    this.setData({
      isWXRefreshing: true
    });
    this.getCardList();
  },
  /**
@@ -163,7 +168,8 @@
    });
    // 更新列表数据
    this.setData({
      allCardPoints: updatedList
      allCardPoints: updatedList,
      isWXRefreshing:false
    });
  },
  handleClost() {
@@ -198,7 +204,7 @@
      this.data.waterAmount = parseInt(this.data.irrigateProfile[index].defaultValue)
      this.setData({
        activeIndex: parseInt(index),
        costiomWater:""
        costiomWater: ""
      });
    }
  },
@@ -431,11 +437,11 @@
    const data = {
      intakeId: this.data.intakeId, //取水口ID
      vcId: this.data.vcId, //虚拟卡ID
      minutes: this.data.waterAmount, //水量
      waterAmount: this.data.waterAmount, //水量
      operator: app.globalData.sessionId //操作员
    };
    post({
      url: "/wx/valve/quantify_close",
      url: "wx/valve/quantify_close",
      data: data
    }).then(response => {
      // 处理成功响应
@@ -472,7 +478,7 @@
      plannedOpenTime: this.data.openTime
    };
    post({
      url: "/wx/valve/planed_open_quantify_close",
      url: "wx/valve/planed_open_quantify_close",
      data: data
    }).then(response => {
      // 处理成功响应
@@ -583,7 +589,7 @@
    }
  },
  //输入自定义水量的监听
  onWaterInputChange(data){
  onWaterInputChange(data) {
    console.log(data.detail.value)
    if (data.detail.value !== "") {
      this.setData({
@@ -597,7 +603,7 @@
    }
  },
  // 定量开泵按钮
  btnOpenOnWater(){
  btnOpenOnWater() {
    if (this.data.waterAmount > 0) {
      if (this.data.isOpenTiming) {
        this.quantifyOpenTime();
@@ -610,7 +616,7 @@
        title: '请选择或输入灌溉时间!',
      })
    }
  }
  },
})
pages/openCard/openCard.wxml
@@ -1,7 +1,7 @@
<!--pages/openCard/openCard.wxml 开卡时的虚拟卡-->
<view class="container">
  <scroll-view class="list-container" scroll-y="true" scroll-x="false">
  <scroll-view class="list-container" scroll-y="true" scroll-x="false" refresher-enabled="true" bindrefresherrefresh="onPullDownRefresh" refresher-triggered="{{isWXRefreshing}}">
    <block wx:if="{{allCardPoints.length > 0}}" wx:for="{{allCardPoints}}" wx:key="index">
      <view class="{{item.inUse===false?'item':'item-gray'}}">
        <view class="item-card">
@@ -132,7 +132,7 @@
    </view>
  </view>
  <!-- 年月日时分 -->
  <t-date-time-picker title="选择日期和时间" visible="{{datetimeVisible}}" mode="minute" value="{{datetime}}" format="YYYY-MM-DD HH:mm" bindchange="onConfirm" bindpick="onColumnChange" bindcancel="hidePicker" start="{{datetime}}"/>
  <t-date-time-picker title="选择日期和时间" visible="{{datetimeVisible}}" mode="minute" value="{{datetime}}" format="YYYY-MM-DD HH:mm" bindchange="onConfirm" bindpick="onColumnChange" bindcancel="hidePicker" start="{{dateStartTime}}" end="{{dateEndTime}}"/>
  <!-- <t-dialog visible="{{showForceConfirm}}" content="当前虚拟卡被占用,是否强制开阀?" confirm-btn="{{ { content: '强制开阀', variant: 'base', theme: 'danger' } }}" cancel-btn="取消" bind:confirm="confirmForceDialog" bind:cancel="cancelDialog" /> -->
  <t-dialog class="error-dialog"  title="开阀错误" visible="{{showErrorDialog}}" content="{{errorData}}" confirm-btn="{{ confirmBtn }}" bind:confirm="closeErrorDialog" />
</view>
pages/openCard/openCard.wxss
@@ -1,6 +1,6 @@
/* pages/openCard/openCard.wxss */
.container {
  height: 100%;
  height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
@@ -117,9 +117,10 @@
.list-container {
  display: flex;
  flex-grow: 1; /* 占满剩余高度 */
  padding-bottom: 30rpx;
  flex: 1;
  height: 100%;
  flex-direction: column; /* 确保内部元素按列排列 */
}
.dialog {
pages/rechargeCard/rechargeCard.js
@@ -9,19 +9,81 @@
   * 页面的初始数据
   */
  data: {
    confirmBtn: { content: '确认', variant: 'base' },
    confirmBtn: {
      content: '确认'
    },
    currentTab: 0, // 当前显示的表格,默认为第一个表格
    allCardPoints: [],
    allWaterPoints:[],
    showDialog:false
    allCardPoints: [{
      "id": "string",
      "inUse": 0,
      "inUseName": "string",
      "money": 110,
      "vcNum": "200030000000"
    }, {
      "id": "string",
      "inUse": 0,
      "inUseName": "string",
      "money": 110,
      "vcNum": "200030000000"
    }, {
      "id": "string",
      "inUse": 0,
      "inUseName": "string",
      "money": 110,
      "vcNum": "200030000000"
    }, {
      "id": "string",
      "inUse": 0,
      "inUseName": "string",
      "money": 110,
      "vcNum": "200030000000"
    }, {
      "id": "string",
      "inUse": 1,
      "inUseName": "string",
      "money": 110,
      "vcNum": "200030000000"
    }],
    allWaterPoints: [{
      "id": "string",
      "inUse": 1,
      "inUseName": "string",
      "money": 110,
      "vcNum": "200030000000"
    },{
      "id": "string",
      "inUse": 1,
      "inUseName": "string",
      "money": 110,
      "vcNum": "200030000000"
    },{
      "id": "string",
      "inUse": 1,
      "inUseName": "string",
      "money": 110,
      "vcNum": "200030000000"
    },{
      "id": "string",
      "inUse": 1,
      "inUseName": "string",
      "money": 110,
      "vcNum": "200030000000"
    },{
      "id": "string",
      "inUse": 1,
      "inUseName": "string",
      "money": 110,
      "vcNum": "200030000000"
    }],
    showDialog: false
  },
 // 切换 Tabs
 switchTab: function (e) {
  const tab = parseInt(e.currentTarget.dataset.tab);
  this.setData({
    currentTab: tab
  });
},
  // 切换 Tabs
  switchTab: function (e) {
    const tab = parseInt(e.currentTarget.dataset.tab);
    this.setData({
      currentTab: tab
    });
  },
  /**
   * 生命周期函数--监听页面加载
   */
@@ -77,58 +139,67 @@
   */
  onShareAppMessage() {
  },//获取虚拟卡列表
  getCardList(){
    get({url:'https://d4x9787456.vicp.fun/sell/virtual_card/get', data: {
      operator: getApp().globalData.sessionId
    }})
    .then((data) => {
      if(data.success&&data.code==="0001"){
        this.setData({
          allCardPoints:  data.content
        });
      }else{
        wx.showToast({
          title: data.msg,
        })
      }
      console.log('Failed to add item:');
    })
    .catch((error) => {
      console.error('Failed to add item:', error);
    });
  }, //获取虚拟卡列表
  getCardList() {
    get({
        url: 'wx/virtual_card/get',
        data: {
          clientId: getApp().globalData.clientId
        }
      })
      .then((data) => {
        if (data.success && data.code === "0001") {
          this.setData({
            allCardPoints: data.content
          });
          this.updateDisplayText();
        } else {
          wx.showToast({
            title: data.msg,
          })
        }
        console.log('Failed to add item:');
      })
      .catch((error) => {
        console.error('Failed to add item:', error);
      });
  },
  getWaterCardList(){
    get({url:'https://d4x9787456.vicp.fun/sell/virtual_card/get', data: {
      operator: getApp().globalData.sessionId
    }})
    .then((data) => {
      if(data.success&&data.code==="0001"){
        this.setData({
          allWaterPoints:  data.content
        });
      }else{
        wx.showToast({
          title: data.msg,
        })
      }
      console.log('Failed to add item:');
    })
    .catch((error) => {
      console.error('Failed to add item:', error);
    });
  getWaterCardList() {
    get({
        url: 'https://d4x9787456.vicp.fun/sell/virtual_card/get',
        data: {
          operator: getApp().globalData.sessionId
        }
      })
      .then((data) => {
        if (data.success && data.code === "0001") {
          this.setData({
            allWaterPoints: data.content
          });
        } else {
          wx.showToast({
            title: data.msg,
          })
        }
        console.log('Failed to add item:');
      })
      .catch((error) => {
        console.error('Failed to add item:', error);
      });
  },
  rechargeCard(item){
  rechargeCard(item) {
    wx.navigateTo({
      url: '/pages/rechargeMoney/rechargMoney' // 首页的路径,根据实际情况填写
    });
  },
  ruinCard(){
  },
  closeDialog(){
  ruinCard() {
    this.setData({
      showDialog:false
      showDialog: true
    })
  },
  closeDialog() {
    this.setData({
      showDialog: false
    })
  }
pages/rechargeCard/rechargeCard.wxml
@@ -15,7 +15,7 @@
  <!-- 虚拟卡 -->
  <scroll-view class="list-container" wx:if="{{currentTab === 0}}" scroll-y="true" scroll-x="false">
    <block wx:if="{{allCardPoints.length > 0}}" wx:for="{{allCardPoints}}" wx:key="index">
      <view class="{{item.inUse===0?'item':'item-gray'}}">
      <view class="{{item.inUse===false?'item':'item-gray'}}">
        <view class="item-card">
          <text class="item-card-text">卡编号:</text>
          <text class="item-card-text">{{item.vcNum}}</text>
pages/valveList/valveList.js
@@ -6,15 +6,31 @@
   */
  data: {
    listData: [{
      intakeNum: "1023356646612"
      intakeNum: "1023356646612",
      watername:"测试",
      startTime:"2024.10.15 12:23",
      endTime:"2024.10.15 16:23"
    }, {
      intakeNum: "1023356646612"
      intakeNum: "1023356646612",
      watername:"测试1",
      startTime:"2024.10.15 12:23",
      endTime:"2024.10.15 16:23"
    }, {
      intakeNum: "1023356646612"
      intakeNum: "1023356646612",
      watername:"测试2",
      startTime:"2024.10.15 12:23",
      endTime:"2024.10.15 16:23"
    }, {
      intakeNum: "1023356646612"
      intakeNum: "1023356646612",
      watername:"测试3",
      startTime:"2024.10.15 12:23",
      endTime:"2024.10.15 16:23"
    }, {
      intakeNum: "1023356646612"
      intakeNum: "1023356646612",
      watername:"测试4",
      startTime:"2024.10.15 12:23",
      endTime:"2024.10.15 16:23"
    }]
  },
pages/valveList/valveList.wxml
@@ -12,9 +12,9 @@
          </view>
        </view>
        <text class="item-text">虚拟卡编号:{{item.intakeNum}}</text>
        <text class="item-text">取水口编号:</text>
        <text class="item-text">开阀时间:</text>
        <text class="item-text">关阀时间:</text>
        <text class="item-text">取水口名称:{{item.watername}}</text>
        <text class="item-text">开阀时间:{{item.startTime}}</text>
        <text class="item-text">关阀时间:{{item.endTime}}</text>
        <view class="item-time">
          <text class="item-text">用水时长:120 分钟</text>
          <text class="item-text">用水量:2 m³</text>
pages/waterIntake/waterIntake.js
@@ -54,16 +54,15 @@
  },
  /**
   * 选择虚拟卡
   * 跳转到选择虚拟卡界面
   * @param {} event 
   */
  choseCard(event) {
    //显示二次确认弹窗
    this.setData({
      showConfirm: true,
      choseItem: event.currentTarget.dataset.item,
      allWaterPoints: []
    })
    this.toOpenCard();
  },
  //开泵通信
  /**
pages/waterIntake/waterIntake.wxss
@@ -139,7 +139,7 @@
}
.dialog{
  --td-dialog-content-font-size:40rpx;
  --td-dialog-content-line-height:50rpx
  --td-dialog-content-line-height:60rpx
}
.error-dialog{