Ver código fonte

feat(miniprogram): 实现用户注册和绑定船舶功能

- 新增用户注册流程,包括获取手机号和绑定船舶信息
- 添加注册弹窗和绑定船舶弹窗界面
- 实现微信登录和获取 openid 功能
- 优化 app.js 中的环境版本检查逻辑
- 更新 index 页面,支持注册和绑定船舶功能
- 调整 wxUtils.js 中的 wxSetSessionKey 方法,处理获取 openid 失败的情况
wzg 8 meses atrás
pai
commit
3b3b98cf50

+ 30 - 22
miniprogram/app.js

@@ -1,4 +1,5 @@
 import { wxSetSessionKey } from "./utils/wxUtils";
+import { postApi } from "./apis/api";
 App({
   onLaunch: function () {
     const updateManager = wx.getUpdateManager();
@@ -24,35 +25,42 @@ App({
       // 新版本下载失败
     });
 
-    wx.cloud.init({
-      traceUser: true,
-    });
+    // wx.cloud.init({
+    //   traceUser: true,
+    // });
     this.globalData = {};
     this.checkEnvVersion();
   },
   onShow() {},
-  checkEnvVersion() {
+  async checkEnvVersion() {
     let v = wx.getAccountInfoSync();
     let appVersion = wx.getStorageSync("appVersion");
     let { envVersion } = v.miniProgram;
-    if (appVersion != envVersion) {
-      // 获取场景值
-      let scene = wx.getLaunchOptionsSync();
-
+    console.log(envVersion);
+    wx.showToast({
+      title: "正在初始化登录信息...",
+      icon: "none",
+    });
+    let { openId, status } = await wxSetSessionKey();
+    let scene = wx.getLaunchOptionsSync(); // 获取场景值
+    let timer = setTimeout(() => {
+      wx.hideLoading();
+      if (appVersion != envVersion) {
+        console.log("清除缓存");
+        wx.clearStorage({
+          success: (res) => {},
+        });
+      }
+      wx.setStorageSync("appVersion", envVersion);
+      wx.setStorageSync("openId", openId);
       // 判断scene.path 是否有sharePage/sharePage
-
-      wx.clearStorage({
-        success: (res) => {
-          wx.setStorageSync("appVersion", envVersion);
-          if (scene.path.indexOf("sharePage/sharePage") === -1) {
-            wx.setStorageSync("appVersion", envVersion);
-            wx.redirectTo({
-              url: "/pages/index/index",
-            });
-          }
-        },
-      });
-    }
-    wxSetSessionKey();
+      if (scene.path.indexOf("sharePage/sharePage") === -1) {
+        wx.setStorageSync("appVersion", envVersion);
+        wx.redirectTo({
+          url: "/pages/index/index",
+        });
+      }
+      clearTimeout(timer);
+    }, 1000);
   },
 });

+ 175 - 19
miniprogram/pages/index/index.js

@@ -7,6 +7,12 @@ Page({
    */
   data: {
     loginStatus: false,
+    regModalVisible: false,
+    bindShipVisible: false,
+    userInfo: {},
+    shipInfo: {},
+    shipName: "", // 新增:船舶名称
+    shipMmsi: "", // 新增:船舶MMSI
   },
 
   async login() {
@@ -14,17 +20,25 @@ Page({
       wx.showToast({
         title: "正在初始化登录信息...",
         icon: "none",
-        duration: 1500,
+        duration: 500,
       });
       wxSetSessionKey();
       return;
     }
     wx.showLoading({
       title: "正在登录...",
+      mask: true,
     });
     let { data } = await postApi("/login/openid", {
       openId: wx.getStorageSync("openId"),
     });
+    await new Promise((resolve) => {
+      setTimeout(() => {
+        resolve();
+      }, 500);
+    });
+    wx.hideLoading();
+
     if (data.status == 0) {
       let obj = {
         ...data.result.userInfo,
@@ -34,32 +48,121 @@ Page({
         wx.setStorageSync(key, obj[key]);
       });
       wx.setStorageSync("accessToken", data.result.tokenInfo.tokenValue);
-    } else {
-      wx.showToast({
-        title: data.msg,
-        icon: "none",
-        duration: 1500,
-      });
-    }
-
-    setTimeout(() => {
-      wx.hideLoading();
       wx.switchTab({
         url: "/pages/takePhoto/takePhoto",
       });
-    }, 1000);
-  },
-  onLoad: function (options) {
-    if (wx.getStorageSync("userId") && wx.getStorageSync("shipName")) {
-      this.setData({
-        loginStatus: true,
-      });
+    } else {
+      wx.setStorageSync("accessToken", data.result.tokenInfo.tokenValue);
+
+      if (data?.result?.userInfo?.userId) {
+        wx.showModal({
+          title: "提示",
+          content: "您已注册但尚未绑定船舶,去绑定?",
+          confirmText: "去绑定",
+          cancelText: "取消",
+          success: (res) => {
+            // 使用箭头函数修正this指向
+            if (res.confirm) {
+              this.setData({
+                bindShipVisible: true,
+              });
+            }
+          },
+        });
+      } else {
+        this.setData({
+          regModalVisible: true,
+        });
+      }
     }
   },
 
+  async init() {
+    let { data } = await postApi("/login/openid", {
+      openId: wx.getStorageSync("openId"),
+    });
+  },
+  hideRegModal() {
+    this.setData({
+      regModalVisible: false,
+    });
+  },
+  async goToRegister(e) {
+    try {
+      if (e.detail.errMsg == "getPhoneNumber:ok") {
+        wx.showLoading({
+          title: "正在登录...",
+          mask: true,
+        });
+        let { data } = await postApi("/wx/getPhoneNumber", {
+          code: e.detail.code,
+        });
+        console.log("data1", data);
+        if (data.status === 0) {
+          let { phoneNumber: phone } = data.result;
+          // let phone = "19103808211";
+          wx.setStorageSync("phone", phone);
+          let { data } = await postApi("/login", {
+            phone,
+            openId: wx.getStorageSync("openId"),
+          });
+          console.log("data2", data);
+          await new Promise((resolve) => {
+            setTimeout(() => {
+              wx.hideLoading();
+              resolve();
+            }, 1500);
+          });
+          if (data.status === 0) {
+            console.log(data, "data2");
+            wx.setStorageSync("accessToken", data.result.tokenInfo.tokenValue);
+          } else {
+            console.log(data, "data23");
+            if (data?.result?.userInfo?.userId) {
+              wx.showModal({
+                title: "提示",
+                content: "您已注册但尚未绑定船舶,去绑定?",
+                confirmText: "去绑定",
+                cancelText: "取消",
+                success: (res) => {
+                  // 使用箭头函数修正this指向
+                  if (res.confirm) {
+                    this.setData({
+                      bindShipVisible: true,
+                      regModalVisible: false, // 关闭注册弹窗
+                    });
+                  }
+                },
+              });
+            } else {
+              wx.showToast({
+                title: data2.msg,
+                icon: "none",
+                duration: 5000,
+              });
+            }
+            this.setData({
+              regModalVisible: false,
+            });
+          }
+        } else {
+          wx.showToast({
+            title: "获取手机号失败",
+            duration: 5000,
+          });
+        }
+      } else {
+        wx.showToast({
+          title: "请授权以登录",
+          icon: "error",
+        });
+      }
+    } catch (error) {}
+  },
+  onLoad: function (options) {},
+
   onShow() {
     let v = wx.getAccountInfoSync();
-
     if (v.miniProgram.envVersion != "release") {
       wx.showToast({
         title: `当前环境:${
@@ -75,4 +178,57 @@ Page({
    * 用户点击右上角分享
    */
   onShareAppMessage: function () {},
+
+  // 隐藏绑定船舶弹窗
+  async hideBindShipModal() {
+    this.setData({
+      bindShipVisible: false,
+      shipName: "", // 清空输入
+      shipMmsi: "", // 清空输入
+    });
+  },
+
+  // 确认绑定船舶
+  async confirmBindShip() {
+    const { shipName, shipMmsi } = this.data;
+    if (!shipName) {
+      wx.showToast({
+        title: "请输入船舶名称",
+        icon: "none",
+      });
+      return;
+    }
+    if (!shipMmsi) {
+      wx.showToast({
+        title: "请输入船舶MMSI",
+        icon: "none",
+      });
+      return;
+    }
+
+    wx.showLoading({
+      title: "正在绑定...",
+      mask: true,
+    });
+    let { data } = await postApi("/register", {
+      shipName,
+      shipMmsi,
+    });
+    if (data.status === 0) {
+      let obj = {
+        ...data.result.userInfo,
+        ...data.result.shipInfo,
+      };
+      Object.keys(obj).forEach(function (key) {
+        wx.setStorageSync(key, obj[key]);
+      });
+      wx.setStorageSync("accessToken", data.result.tokenInfo.tokenValue);
+    } else {
+      wx.showToast({
+        title: data.msg,
+        icon: "none",
+        duration: 5000,
+      });
+    }
+  },
 });

+ 29 - 2
miniprogram/pages/index/index.wxml

@@ -1,3 +1,30 @@
 <image class="main" mode="aspectFit" src="../../images/index.png"></image>
-<view bindtap="login" class="go">{{loginStatus?'去拍照':'去体验'}}</view>
-<!-- <view wx:if="{{!loginStatus}}" class="has-account">已有账号,去登录</view> -->
+<view bindtap="login" class="go">去拍照</view>
+<view wx:if="{{regModalVisible}}" class="reg-mask" catchtouchmove="preventTouchMove">
+    <view class="reg-mask-content">
+        <view class="reg-mask-text">您还未注册,是否注册?</view>
+        <view class="reg-mask-buttons">
+            <button class="reg-mask-button cancel" bindtap="hideRegModal">取消</button>
+            <button class="reg-mask-button register" open-type="getPhoneNumber" bindgetphonenumber="goToRegister">
+                去注册
+            </button>
+        </view>
+    </view>
+</view>
+<view wx:if="{{bindShipVisible}}" class="bind-ship">
+    <view class="bind-ship-content">
+        <view class="bind-ship-title">绑定船舶</view>
+        <view class="line">
+            <view class="label">船舶名称:</view>
+            <input class="input" model:value="{{shipName}}" type="text" placeholder="请输入船舶名称" />
+        </view>
+        <view class="line">
+            <view class="label">MMSI:</view>
+            <input class="input" model:value="{{shipMmsi}}" type="number" placeholder="请输入船舶MMSI" />
+        </view>
+        <view class="buttons">
+            <button class="button cancel" bindtap="hideBindShipModal">取消</button>
+            <button class="button confirm" bindtap="confirmBindShip">确认绑定</button>
+        </view>
+    </view>
+</view>

+ 132 - 1
miniprogram/pages/index/index.wxss

@@ -25,6 +25,7 @@ image {
   border-radius: 6vw;
   margin: 0 auto;
   margin-top: 60rpx;
+  padding: 0;
 }
 
 .has-account {
@@ -36,4 +37,134 @@ image {
   font-size: 32rpx;
   text-align: center;
   margin: 30rpx auto;
-}
+}
+
+.reg-mask {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background-color: rgba(0, 0, 0, 0.5);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  z-index: 999;
+}
+
+.reg-mask-content {
+  background-color: #fff;
+  padding: 60rpx 40rpx;
+  border-radius: 10rpx;
+  text-align: center;
+  width: 80vw;
+}
+
+.reg-mask-text {
+  font-size: 36rpx;
+  color: #333;
+  text-align: center;
+  font-weight: bold;
+  margin-bottom: 40rpx;
+}
+
+.reg-mask-buttons {
+  display: flex;
+  justify-content: space-around;
+}
+
+.reg-mask-button {
+  padding: 16rpx 10rpx !important;
+  width: 200rpx !important;
+  border-radius: 8rpx;
+  font-size: 30rpx;
+}
+
+.reg-mask-button.cancel {
+  background-color: #eee;
+  color: #333;
+  border: 1rpx solid #ccc;
+}
+
+.reg-mask-button.register {
+  background-color: #3e94f6;
+  color: #fff;
+  border: 1rpx solid #3e94f6;
+}
+
+.bind-ship {
+  background-color: rgba(0, 0, 0, 0.5);
+  height: 100vh;
+  width: 100vw;
+  position: fixed;
+  top: 0;
+  left: 0;
+  z-index: 999;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.bind-ship-content {
+  background-color: #fff;
+  padding: 60rpx 40rpx;
+  border-radius: 10rpx;
+  width: 80vw;
+  box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
+}
+
+.bind-ship-title {
+  font-size: 36rpx;
+  color: #333;
+  text-align: center;
+  font-weight: bold;
+  margin-bottom: 40rpx;
+}
+
+.bind-ship .line {
+  display: flex;
+  align-items: center;
+  margin-bottom: 30rpx;
+}
+
+.bind-ship .label {
+  width: 180rpx;
+  font-size: 32rpx;
+  color: #555;
+  text-align: right;
+  padding-right: 20rpx;
+}
+
+.bind-ship .input {
+  flex: 1;
+  height: 80rpx;
+  border: 1rpx solid #ddd;
+  border-radius: 8rpx;
+  padding: 0 20rpx;
+  font-size: 30rpx;
+}
+
+.bind-ship .buttons {
+  display: flex;
+  justify-content: space-around;
+  margin-top: 50rpx;
+}
+
+.bind-ship .button {
+  padding: 16rpx 10rpx !important;
+  width: 200rpx !important;
+  border-radius: 8rpx;
+  font-size: 30rpx;
+}
+
+.bind-ship .button.cancel {
+  background-color: #eee;
+  color: #333;
+  border: 1rpx solid #ccc;
+}
+
+.bind-ship .button.confirm {
+  background-color: #3e94f6;
+  color: #fff;
+  border: 1rpx solid #3e94f6;
+}

+ 43 - 7
miniprogram/utils/wxUtils.js

@@ -5,14 +5,50 @@ function wxSetSessionKey() {
   return new Promise((resolve, reject) => {
     wx.login({
       success: async (res) => {
-        let { data } = await postApi("/wx/getOpenId", {
-          code: res.code,
+        if (res.code) {
+          let { data } = await postApi("/wx/getOpenId", {
+            code: res.code,
+          });
+          if (data.status === 0) {
+            let { openId } = data.result;
+            // let openId = "oiOWR5ch3L_mD2uYwSemzedDdG8I232";
+            wx.setStorageSync("openId", openId);
+            resolve({
+              status: 0,
+              openId,
+            });
+          } else {
+            wx.showToast({
+              title: `系统错误: status: ${data.status} , ${data.msg}`,
+              icon: "none",
+              duration: 5000,
+            });
+            reject({
+              openId: "",
+              status: 1,
+            });
+          }
+        } else {
+          wx.showToast({
+            title: "获取openId失败,请重新进入小程序",
+            icon: "none",
+            duration: 5000,
+          });
+          reject({
+            openId: "",
+            status: 1,
+          });
+        }
+      },
+      fail: (e) => {
+        wx.showToast({
+          title: "获取openId失败,请重新进入小程序",
+          icon: "none",
+          duration: 5000,
         });
-        let { openId } = data.result;
-        // let openId = "oiOWR5ch3L_mD2uYwSemzedDdG8I222222222";
-        wx.setStorageSync("openId", openId);
-        resolve({
-          openId,
+        reject({
+          openId: "",
+          status: 1,
         });
       },
     });