沙盘演示系统应用的微信小程序
pages/home/home.js
@@ -4,6 +4,7 @@
  get,
  post
} = require('../../api/request.js');
const app = getApp();
Page({
  /**
@@ -15,8 +16,8 @@
    myItem: {},
    waterIntakeName: "",
    image: "/images/ic_head_bg.jpg",
    userPhone: "158****0723",
    userName: "张三",
    userPhone: "未登录",
    userName: "点击登录",
    scrollViewHeight: 0,
    listData: [],
    isRefreshing: false,
@@ -28,13 +29,26 @@
    },
    errorDialogTitle: "关阀错误",
    showForceConfirm: false, //是否强制开阀
    lastIntakeName: ""
    lastIntakeName: "",
    isLogin: false, //是否已经登录
    showInfoDialog: false,
    showTipDialog: false,
    options: '',
    showUnBind: false,
    useTestData: false  // 新增:是否使用测试数据的标志
  },
  openValve: function (e) {
    wx.navigateTo({
      url: '/pages/waterIntake/waterIntake',
    })
    if (this.data.isLogin) {
      wx.navigateTo({
        url: '/pages/waterIntake/waterIntake',
      })
    } else {
      wx.showToast({
        title: '请先登录',
        icon: 'error'
      })
    }
  },
  calculateScrollViewHeight: function () {
    wx.createSelectorQuery().selectAll('.list-item').boundingClientRect((rects) => {
@@ -45,16 +59,29 @@
    }).exec();
  },
  startPullDownRefresh() {
    if (!this.data.isWXRefreshing) {
      var self = this;
      console.log(this.data.isRefreshing);
    if (this.data.useTestData) {
      this.setData({
        isRefreshing: true
      });
      this.getOpenList();
      return;
    }
    if (this.data.isLogin) {
      if (!this.data.isWXRefreshing) {
        var self = this;
        console.log(this.data.isRefreshing);
        this.setData({
          isRefreshing: true
        });
        this.getOpenList();
      }
    } else {
      wx.showToast({
        title: '请先登录',
        icon: 'error'
      })
    }
  },
  //获取用户数据
  getUserData() {
@@ -68,61 +95,135 @@
        console.error('Failed to fetch data:', error);
      });
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    //判断本地是否保存sessionId
    // 使用 wx.nextTick 等待页面渲染完成
    wx.nextTick(() => {
      this.calculateScrollViewHeight();
    });
    //当开阀成功后调用刷新
    console.log("onLoad:" + options.param);
    if (options.param) {
      wx.showToast({
        title: '开阀成功',
        icon: 'success',
        duration: 3000
    if (options.param === "1" || options.param === "2") {
      this.setData({
        options: options,
        isLogin: true,
      })
      this.getOpenList();
    }
    this.initData();
  },
  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {
    // 直接加载测试数据
    if (this.data.useTestData) {
      this.setData({
        isLogin: true, // 设置为已登录状态以便能看到测试数据
        userName: "测试用户",
        userPhone: "135****6789"
      });
      this.getOpenList();
      return;
    }
    //判断本地是否保存sessionId
    if (storage.isHasKeySync("sessionId")) {
      const app = getApp();
      storage.getItem('sessionId').then((data) => {
        app.globalData.sessionId = data;
        this.setData({
          isLogin: true
        })
        if (app.globalData.sessionId) {
          this.getUserDataBySession();
        }
      }).catch((err) => {});
      storage.getItem('clientId').then((data) => {
        app.globalData.clientId = data;
        this.getOpenList();
      }).catch((err) => {});
    } else {
      //本地没有缓存微信登录
      this.wxLogin();
    }
    if (this.data.options.param === "1") {
      this.setData({
        showTipDialog: true,
        tipData: "开阀命令下发成功,因开阀需要时间,约20-60秒后可刷新快速关阀列表查看执行结果。"
      })
      setTimeout(() => {
        this.getOpenList();
      }, 20000)
    } else if (this.data.options.param === "2") {
      this.setData({
        showTipDialog: true,
        tipData: "预约开阀命令下发成功,当到达预约时间并且成功开阀后快速关阀列表会显示未关阀记录"
      })
      this.getOpenList();
    }
  },
  wxLogin() {
    // if (!this.data.isLogin) {
      const that = this;
      wx.login({
        success: function (res) {
          if (res.code) {
            var code = res.code;
            console.log(code);
            // 将code发送到服务器获取openid
            that.codeLogin(code);
          } else {
            console.log('登录失败!' + res.errMsg);
          }
        }
      });
    // }
  },
  //微信code登录
  codeLogin(codeData) {
    wx.showLoading({
      title: '正在登录请稍候...', // 加载提示文字
      mask: true // 是否显示透明蒙层,防止触摸穿透,默认为 false
    });
    const data = {
      code: codeData, //临时登录凭证
    };
    post({
      url: "wx/client/code_login",
      data: data,
    }).then(response => {
      // 处理成功响应
      console.log('请求成功:', response);
      // 加载完成后隐藏加载动画
      wx.hideLoading();
      if (response.code === "0001") {
        //假如为空则跳转到绑定界面
        if (response.content.client.clientId === "") {
          wx.navigateTo({
            url: '/pages/wxbind/wxbind'
          })
        } else {
          //缓存在本地
          this.setData({
            isLogin: true
          })
          getApp().globalData.sessionId = response.content.client.sessionId
          storage.setItem("sessionId", response.content.client.sessionId)
          getApp().globalData.clientId = response.content.client.clientId
          storage.setItem("clientId", response.content.client.clientId)
          this.initData();
        }
      } else {
  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {
      }
    }).catch(error => {
      // 加载完成后隐藏加载动画
      wx.hideLoading();
      // 处理错误响应
      console.error('请求失败:', error);
    });
  },
  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {
  },
  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload() {
  },
  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
@@ -137,43 +238,45 @@
    // 数据请求完成后,停止下拉刷新的动画
    this.getOpenList();
  },
  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {
  },
  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {
  },
  // 充值
  recharge() {
    // wx.navigateTo({
    //   url: '/pages/rechargeCard/rechargeCard',
    // })
    wx.showToast({
      title: '暂未开放',
      icon: 'none'
    })
    if (this.data.isLogin) {
      wx.navigateTo({
        url: '/pages/rechargeCard/rechargeCard',
      })
    } else {
      wx.showToast({
        title: '请先登录',
        icon: 'error'
      })
    }
  },
  //开关阀记录
  openValveList() {
    // wx.navigateTo({
    //   url: '/pages/valveList/valveList',
    // })
    wx.showToast({
      title: '暂未开放',
      icon: 'none'
    })
    if (this.data.isLogin) {
      wx.navigateTo({
        url: '/pages/valveList/valveList',
      })
    } else {
      wx.showToast({
        title: '请先登录',
        icon: 'error'
      })
    }
  },
  //问题反馈
  feedBack() {
    wx.showToast({
      title: '暂未开放',
      icon: 'none'
    })
    if (this.data.isLogin) {
      wx.navigateTo({
        url: '/pages/feedback/feedback',
      })
    } else {
      wx.showToast({
        title: '请先登录',
        icon: 'error'
      })
    }
  },
  handleChange(e) {
    const item = e.currentTarget.dataset.item;
@@ -189,13 +292,16 @@
    this.setData({
      showConfirm: false,
      showErrorDialog: false,
      showForceConfirm: false
      showForceConfirm: false,
      showTipDialog: false
    });
  },
  cancelDialog() {
    this.setData({
      showForceConfirm: false,
      showConfirm: false
      showConfirm: false,
      showTipDialog: false,
      showUnBind: false
    });
  },
  /**
@@ -229,11 +335,23 @@
      // 加载完成后隐藏加载动画
      wx.hideLoading();
      this.getOpenList();
      wx.showToast({
        title: '关阀成功',
        icon: 'success',
        duration: 3000
      })
      if (response.content.data.success) {
        this.setData({
          isLogin: true,
          showTipDialog: true,
          tipData: "关阀命令下发成功,约20-60秒后可刷新快速关阀列表查看执行结果。"
        })
        setTimeout(() => {
          this.getOpenList();
        }, 40000)
      } else {
        wx.showToast({
          title: '命令执行失败',
          icon: 'error',
          duration: 3000
        })
      }
    }).catch(error => {
      wx.hideLoading();
      this.setData({
@@ -243,38 +361,123 @@
      })
      // 处理错误响应
      console.error('请求失败:', error);
    });
  },
  /**
   * 生成测试数据 - 新增函数
   */
  generateTestData() {
    const now = new Date();
    const year = now.getFullYear();
    const month = String(now.getMonth() + 1).padStart(2, '0');
    const day = String(now.getDate()).padStart(2, '0');
    const hours = String(now.getHours()).padStart(2, '0');
    const minutes = String(now.getMinutes()).padStart(2, '0');
    const seconds = String(now.getSeconds()).padStart(2, '0');
    const dateString = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
    const orderBase = `TEST-${year}${month}${day}-`;
    const testData = [
      {
        intakeNum: "取水口1",
        isOnLine: true,
        dt: dateString,
        waterInstant: "1.23",
        orderNo: orderBase + "001",
        rtuAddr: "TEST-RTU-001",
        vcNum: "TEST-VC-001",
        planned: false,
        time: this.extractTime(dateString),
        deleteText: "删除",
        displayText: "关阀",
        isOpen: true
      },
      {
        intakeNum: "取水口2",
        isOnLine: false,
        dt: dateString,
        waterInstant: "2.45",
        orderNo: orderBase + "002",
        rtuAddr: "TEST-RTU-002",
        vcNum: "TEST-VC-002",
        planned: false,
        time: this.extractTime(dateString),
        deleteText: "删除",
        displayText: "关阀",
        isOpen: true
      },
      {
        intakeNum: "取水口3",
        isOnLine: true,
        dt: dateString,
        waterInstant: "3.67",
        orderNo: orderBase + "003",
        rtuAddr: "TEST-RTU-003",
        vcNum: "TEST-VC-003",
        planned: true,
        time: this.extractTime(dateString),
        deleteText: "删除",
        displayText: "取消",
        isOpen: true
      }
    ];
    return testData;
  },
  /**
   * 获取为关阀记录
   */
  getOpenList() {
    const app = getApp();
    const params = {
      url: 'wx/valve/get',
      data: {
        operator: app.globalData.sessionId
    if (this.data.isLogin) {
      // 如果设置了使用测试数据,则直接使用测试数据
      if (this.data.useTestData) {
        const testData = this.generateTestData();
        this.setData({
          listData: testData,
          isRefreshing: false,
          isWXRefreshing: false,
        });
        this.updateDisplayText();
        return;
      }
    };
    get(params).then(data => {
      this.setData({
        listData: data.content,
        isRefreshing: false, // 将triggered属性设置为false,表示下拉刷新已完成
        isWXRefreshing: false, // 将triggered属性设置为false,表示下拉刷新已完成
      })
    }).catch(err => {
      // 错误回调
      this.setData({
        isRefreshing: false, // 将triggered属性设置为false,表示下拉刷新已完成
        isWXRefreshing: false, // 将triggered属性设置为false,表示下拉刷新已完成
      })
      const app = getApp();
      const params = {
        url: 'wx/valve/get',
        data: {
          operator: app.globalData.clientId
        }
      };
      get(params).then(data => {
        this.setData({
          listData: data.content,
          isRefreshing: false, // 将triggered属性设置为false,表示下拉刷新已完成
          isWXRefreshing: false, // 将triggered属性设置为false,表示下拉刷新已完成
        })
        this.updateDisplayText();
      }).catch(err => {
        // 错误回调
        this.setData({
          isRefreshing: false, // 将triggered属性设置为false,表示下拉刷新已完成
          isWXRefreshing: false, // 将triggered属性设置为false,表示下拉刷新已完成
        })
        wx.showToast({
          title: err.msg,
          icon: 'error',
          duration: 3000
        })
      });
    } else {
      wx.showToast({
        title: err.msg,
        icon: 'error',
        duration: 3000
        title: '请先登录',
        icon: 'error'
      })
    });
      this.setData({
        isRefreshing: false, // 将triggered属性设置为false,表示下拉刷新已完成
        isWXRefreshing: false, // 将triggered属性设置为false,表示下拉刷新已完成
      })
    }
  },
  /**
   * 确认关闭回调
@@ -284,6 +487,30 @@
    this.setData({
      showConfirm: false
    });
    if (this.data.useTestData) {
      // 测试数据模式下,模拟关阀操作
      wx.showLoading({
        title: '正在关阀请稍候...',
        mask: true
      });
      // 模拟请求延迟
      setTimeout(() => {
        wx.hideLoading();
        // 从列表中移除被关闭的阀门
        const updatedList = this.data.listData.filter(item =>
          item.orderNo !== this.data.myItem.orderNo
        );
        this.setData({
          listData: updatedList,
          showTipDialog: true,
          tipData: "关阀命令下发成功,约20-60秒后可刷新快速关阀列表查看执行结果。"
        });
      }, 1500);
      return;
    }
    this.postCloseValaue(this.data.myItem.orderNo, this.data.myItem.rtuAddr, this.data.myItem.vcNum);
  },
  //根据session获取农户信息
@@ -298,7 +525,8 @@
    get(params).then(data => {
      this.setData({
        userName: data.content.clientName,
        userPhone: this.maskPhoneNumber(data.content.phone)
        userPhone: this.maskPhoneNumber(data.content.phone),
        isLogin: true
      })
    }).catch(err => {
      // 错误回调
@@ -327,28 +555,36 @@
   * 扫码开阀
   */
  scenCode() {
    const that = this;
    wx.scanCode({
      success(res) {
        console.log(res.result); // 当且仅当扫码为非微信二维码时,会返回result
        if (res.result.startsWith("content://")) {
          let jsonStr = res.result.replace("content://", "")
          try {
            that.saveData(jsonStr)
          } catch (error) {
            console.error('Error parsing JSON:', error);
    if (this.data.isLogin) {
      const that = this;
      wx.scanCode({
        success(res) {
          console.log(res.result); // 当且仅当扫码为非微信二维码时,会返回result
          if (res.result.startsWith("content://")) {
            let jsonStr = res.result.replace("content://", "")
            try {
              that.saveData(jsonStr)
            } catch (error) {
              console.error('Error parsing JSON:', error);
            }
          } else {
            wx.navigateTo({
              url: '/pages/openCard/openCard?intakeName=' + res.result,
            })
            // that.postOppenValva()
          }
        } else {
          that.postOppenValva(res.result)
        },
        fail(err) {
          console.error(err);
        }
      })
    } else {
      wx.showToast({
        title: '请先登录',
        icon: 'error'
      })
    }
      },
      fail(err) {
        console.error(err);
      }
    })
  },
  confirmForceDialog() {
    console.log("confirmForceDialog");
@@ -358,7 +594,7 @@
    this.postOppenValva(this.data.lastIntakeName, true)
  },
  /**
   *
   * 扫码开阀调用开阀接口
   * @param {*} intakeName 
   */
  postOppenValva(intakeName, isforce) {
@@ -421,8 +657,7 @@
  //进入界面获取界面数据
  initData() {
    const app = getApp();
    console.log("tag>>>>:" +app.globalData.tag)
    console.log("tag>>>>:" + app.globalData.tag)
    if (storage.isHasKeySync("userData")) {
      storage.getItem('userData').then((data) => {
        let jsonObj = JSON.parse(data);
@@ -439,6 +674,189 @@
      this.getOpenList();
      console.log('Failed to load parameter:false');
    }
  },
  //强制删除
  onDelete(e) {
    const item = e.currentTarget.dataset.item;
    const that = this;
    if (this.data.useTestData) {
      // 测试数据模式下,模拟删除操作
      wx.showLoading({
        title: '正在强制删除请稍候...',
        mask: true
      });
      // 模拟请求延迟
      setTimeout(() => {
        wx.hideLoading();
        // 从列表中移除被删除的项
        const updatedList = this.data.listData.filter(listItem =>
          listItem.orderNo !== item.orderNo
        );
        this.setData({
          listData: updatedList
        });
        wx.showToast({
          title: '删除成功',
          icon: 'success',
          duration: 2000
        });
      }, 1500);
      return;
    }
    wx.showLoading({
      title: '正在强制删除请稍候...', // 加载提示文字
      mask: true // 是否显示透明蒙层,防止触摸穿透,默认为 false
    });
    const data = {
      vcNum: item.vcNum, //取水口ID
      rtuAddr: item.rtuAddr, //阀控器地址
    };
    post({
      url: "wx/valve/deleteUnclosed",
      data: data,
      timeout: 180000
    }).then(response => {
      // 处理成功响应
      console.log('请求成功:', response);
      // 加载完成后隐藏加载动画
      wx.hideLoading();
      //重新获取列表刷新数据
      this.getOpenList();
    }).catch(error => {
      // 加载完成后隐藏加载动画
      wx.hideLoading();
      // 处理错误响应
      console.error('请求失败:', error);
    });
  },
  //修改按钮文字
  updateDisplayText() {
    const updatedList = this.data.listData.map(item => {
      let displayText = '';
      if (item.planned) {
        displayText = '取消';
      } else {
        displayText = "关阀"
      }
      let deleteText = "删除"
      let time;
      if (!item.dt) {
        time = "暂无"
      } else {
        time = this.extractTime(item.dt)
      }
      if (item.waterInstant===null) {
        item.waterInstant = "暂无"
      }
      return {
        ...item,
        displayText,
        deleteText,
        time
      }; // 保留所有其他字段,并添加 displayText 字段
    });
    // 更新列表数据
    this.setData({
      listData: updatedList
    });
  },
  //解绑
  unbind() {
    this.setData({
      showUnBind: true
    })
  },
  //确认解绑
  unBindPost() {
    this.setData({
      showUnBind: false
    })
    wx.showLoading({
      title: '正在解绑请稍候...', // 加载提示文字
      mask: true // 是否显示透明蒙层,防止触摸穿透,默认为 false
    });
    const data = {
      sessionId: getApp().globalData.sessionId //取水口ID
    };
    post({
      url: 'wx/client/unbind',
      data: data,
      useParams: true
    }).then(response => {
      // 处理成功响应
      console.log('请求成功:', response);
      // 加载完成后隐藏加载动画
      wx.hideLoading();
      //清空数据
      this.setData({
        userPhone: "请登录",
        userName: "未登录",
        listData: [],
        isLogin: false
      })
      app.globalData.sessionId = "";
      app.globalData.clientId = ""
      storage.removeItem("sessionId")
      storage.removeItem("clientId")
      wx.showToast({
        title: '解绑成功',
        icon: 'success',
        duration: 3000
      })
    }).catch(error => {
      // 加载完成后隐藏加载动画
      wx.hideLoading();
      // 处理错误响应
      console.error('请求失败:', error);
      wx.showToast({
        title: '解绑失败',
        icon: 'error',
        duration: 3000
      })
    });
  },
  //点击提示按钮
  infoShow() {
    this.setData({
      showInfoDialog: true
    })
  },
  //提示窗确认按钮
  confirmBtnInfoDialog() {
    this.setData({
      showInfoDialog: false
    })
  },
  //处理时间去掉年月日
  extractTime(datetimeString) {
    const formattedDate = datetimeString.replace(" ", "T");
    const date = new Date(formattedDate);
    // 获取小时、分钟和秒
    const hours = date.getHours().toString().padStart(2, '0');
    const minutes = date.getMinutes().toString().padStart(2, '0');
    const seconds = date.getSeconds().toString().padStart(2, '0');
    return `${hours}:${minutes}:${seconds}`;
  },
  onShareAppMessage: function (options) {
    // 设置分享内容
    return {
      title: '大禹灌溉助手', // 分享标题
      path: '/pages/home/home', // 分享路径,该路径需要是当前小程序存在的页面路径
      imageUrl: '/images/logo2.jpg', // 分享图标,可以是网络图片路径或本地图片路径
      success: function (res) {
        // 分享成功的回调函数
      },
      fail: function (res) {
        // 分享失败的回调函数
      }
    };
  }
})