Pārlūkot izejas kodu

refactor:小程序快捷登录重构

kele 2 gadi atpakaļ
vecāks
revīzija
18cd88872c

+ 8 - 0
sheep/api/user.js

@@ -102,6 +102,14 @@ export default {
       },
     }),
 
+  // 更新小程序信息
+  updateMpUserInfo: (data) =>
+    request({
+      url: '/user/api/user/updateMpUserInfo',
+      method: 'POST',
+      data,
+    }),
+
   // 第三方授权信息
   thirdOauthInfo: () =>
     request({

+ 3 - 4
sheep/components/s-auth-modal/components/account-login.vue

@@ -43,10 +43,6 @@
           </template>
         </uni-easyinput>
       </uni-forms-item>
-
-      <button class="ss-reset-button type-btn" @tap="showAuthModal('smsRegister')">
-        立即注册
-      </button>
     </uni-forms>
   </view>
 </template>
@@ -59,6 +55,8 @@
 
   const accountLoginRef = ref(null);
 
+  const emits = defineEmits(['onConfirm']);
+
   const props = defineProps({
     agreeStatus: {
       type: Boolean,
@@ -89,6 +87,7 @@
 
     // 同意协议
     if (!props.agreeStatus) {
+      emits('onConfirm', true)
       sheep.$helper.toast('请勾选同意');
       return;
     }

+ 145 - 0
sheep/components/s-auth-modal/components/mp-authorization.vue

@@ -0,0 +1,145 @@
+<!-- 微信授权信息 mpAuthorization  -->
+<template>
+  <view>
+    <!-- 标题栏 -->
+    <view class="head-box ss-m-b-60 ss-flex-col">
+      <view class="ss-flex ss-m-b-20">
+        <view class="head-title ss-m-r-40 head-title-animation">授权信息</view>
+      </view>
+      <view class="head-subtitle">完善您的头像、昵称、手机号</view>
+    </view>
+
+    <!-- 表单项 -->
+    <uni-forms
+      ref="accountLoginRef"
+      v-model="state.model"
+      :rules="state.rules"
+      validateTrigger="bind"
+      labelWidth="140"
+      labelAlign="center"
+    >
+      <uni-forms-item name="avatar" label="头像">
+        <button
+          class="ss-reset-button avatar-btn"
+          open-type="chooseAvatar"
+          @chooseavatar="onChooseAvatar"
+        >
+          <image
+            class="avatar-img"
+            :src="sheep.$url.cdn(state.model.avatar)"
+            mode="aspectFill"
+            @tap="sheep.$router.go('/pages/user/info')"
+          ></image>
+          <text class="cicon-forward"></text>
+        </button>
+      </uni-forms-item>
+      <uni-forms-item name="nickname" label="昵称">
+        <uni-easyinput
+          type="nickname"
+          placeholder="请输入昵称"
+          v-model="state.model.nickname"
+          :inputBorder="false"
+        >
+        </uni-easyinput>
+      </uni-forms-item>
+
+      <view class="foot-box">
+        <button class="ss-reset-button authorization-btn" @tap="onConfirm"> 确认授权 </button>
+      </view>
+    </uni-forms>
+  </view>
+</template>
+
+<script setup>
+  import { computed, watch, ref, reactive, unref } from 'vue';
+  import sheep from '@/sheep';
+  import { showAuthModal, closeAuthModal } from '@/sheep/hooks/useModal';
+
+  const props = defineProps({
+    agreeStatus: {
+      type: Boolean,
+      default: false,
+    },
+  });
+
+  const userInfo = computed(() => sheep.$store('user').userInfo);
+
+  const accountLoginRef = ref(null);
+
+  // 数据
+  const state = reactive({
+    model: {
+      nickname: userInfo.value.nickname,
+      avatar: userInfo.value.avatar,
+    },
+    rules: {
+
+    },
+    disabledStyle: {
+      color: '#999',
+      disableColor: '#fff',
+    },
+  });
+  // 选择头像
+  function onChooseAvatar(e) {
+    const tempUrl = e.detail.avatarUrl || '';
+    uploadAvatar(tempUrl);
+  }
+  async function uploadAvatar(tempUrl) {
+    if (!tempUrl) return;
+    let { path } = await sheep.$api.app.upload(tempUrl, 'ugc');
+    state.model.avatar = path;
+  }
+
+  // 确认授权
+  async function onConfirm() {
+    const { model } = state;
+    const { nickname, avatar } = model;
+    if (!nickname) {
+      sheep.$helper.toast('请输入昵称');
+      return;
+    }
+    if (!avatar) {
+      sheep.$helper.toast('请选择头像');
+      return;
+    }
+    const { error, msg } = await sheep.$api.user.updateMpUserInfo(model);
+    if (error === 0) {
+      sheep.$helper.toast('授权成功');
+      await sheep.$store('user').getInfo();
+      closeAuthModal();
+    }else {
+      sheep.$helper.toast(msg);
+    }
+  }
+</script>
+
+<style lang="scss" scoped>
+  @import '../index.scss';
+
+  .foot-box {
+    width: 100%;
+    display: flex;
+    justify-content: center;
+  }
+  .authorization-btn {
+    width: 686rpx;
+    height: 80rpx;
+    background-color: var(--ui-BG-Main);
+    border-radius: 40rpx;
+    color: #fff;
+  }
+  .avatar-img {
+    width: 72rpx;
+    height: 72rpx;
+    border-radius: 36rpx;
+  }
+  .cicon-forward {
+    font-size: 30rpx;
+    color: #595959;
+  }
+  .avatar-btn {
+    width: 100%;
+    justify-content: space-between;
+  }
+</style>

+ 3 - 3
sheep/components/s-auth-modal/components/sms-login.vue

@@ -55,8 +55,6 @@
         </uni-easyinput>
       </uni-forms-item>
     </uni-forms>
-
-    <button class="ss-reset-button type-btn" @tap="showAuthModal('smsRegister')"> 立即注册 </button>
   </view>
 </template>
 
@@ -65,10 +63,11 @@
   import sheep from '@/sheep';
   import { code, mobile } from '@/sheep/validate/form';
   import { showAuthModal, closeAuthModal, getSmsCode, getSmsTimer } from '@/sheep/hooks/useModal';
-  import throttle from '@/sheep/helper/throttle';
 
   const smsLoginRef = ref(null);
 
+  const emits = defineEmits(['onConfirm']);
+
   const props = defineProps({
     agreeStatus: {
       type: Boolean,
@@ -100,6 +99,7 @@
     if (!validate) return;
 
     if (!props.agreeStatus) {
+      emits('onConfirm', true)
       sheep.$helper.toast('请勾选同意');
       return;
     }

+ 4 - 0
sheep/components/s-auth-modal/components/sms-register.vue

@@ -80,8 +80,11 @@
   });
 
   const smsRegisterRef = ref(null);
+  
   const isLogin = computed(() => sheep.$store('user').isLogin);
 
+  const emits = defineEmits(['onConfirm']);
+
   // 数据
   const state = reactive({
     isMobileEnd: false, // 手机号输入完毕
@@ -107,6 +110,7 @@
     if (!validate) return;
 
     if (!props.agreeStatus) {
+      emits('onConfirm',true);
       sheep.$helper.toast('请勾选同意');
       return;
     }

+ 112 - 22
sheep/components/s-auth-modal/s-auth-modal.vue

@@ -6,41 +6,56 @@
       <account-login
         v-if="authType === 'accountLogin'"
         :agreeStatus="state.protocol"
-      ></account-login>
+        @onConfirm="onConfirm"
+      />
 
       <!-- 2.短信登录  smsLogin -->
-      <sms-login v-if="authType === 'smsLogin'" :agreeStatus="state.protocol"></sms-login>
+      <sms-login v-if="authType === 'smsLogin'" :agreeStatus="state.protocol" @onConfirm="onConfirm" />
+
       <!-- 3.短信注册 smsRegister-->
-      <sms-register v-if="authType === 'smsRegister'" :agreeStatus="state.protocol"></sms-register>
+      <sms-register
+        v-if="authType === 'smsRegister'"
+        :agreeStatus="state.protocol"
+        @onConfirm="onConfirm"
+      />
 
       <!-- 4.忘记密码 resetPassword-->
-      <reset-password v-if="authType === 'resetPassword'"></reset-password>
+      <reset-password v-if="authType === 'resetPassword'" />
 
       <!-- 5.绑定手机号 changeMobile -->
-      <change-mobile v-if="authType === 'changeMobile'"></change-mobile>
+      <change-mobile v-if="authType === 'changeMobile'" />
 
       <!-- 6.修改密码 changePassword-->
-      <change-passwrod v-if="authType === 'changePassword'"></change-passwrod>
+      <change-passwrod v-if="authType === 'changePassword'" />
 
       <!-- 7.修改用户名 changeUsername-->
-      <change-username v-if="authType === 'changeUsername'"></change-username>
+      <change-username v-if="authType === 'changeUsername'" />
+
+      <!-- 8.微信小程序授权 changeUsername-->
+      <mp-authorization v-if="authType === 'mpAuthorization'" />
 
-      <!-- 第三方登录 -->
+      <!-- 第三方登录+注册 -->
       <view
         v-if="['accountLogin', 'smsLogin'].includes(authType)"
-        class="auto-login-box ss-flex ss-row-center ss-col-center"
+        class="auto-login-box ss-flex ss-flex-col ss-row-center ss-col-center"
       >
-        <!-- 微信小程序登录 -->
+        <!-- 立即注册&快捷登录 TextButton -->
+        <view v-if="sheep.$platform.name === 'WechatMiniProgram'" class="ss-flex register-box">
+          <view class="register-title">还没有账号?</view>
+          <button class="ss-reset-button register-btn" @tap="showAuthModal('smsRegister')"
+            >立即注册</button
+          >
+          <view class="or-title">或</view>
+          <button class="ss-reset-button login-btn" @tap="thirdLogin('wechat')">快捷登录</button>
+          <view class="circle"></view>
+        </view>
+
         <button
-          v-if="sheep.$platform.name === 'WechatMiniProgram'"
-          open-type="getPhoneNumber"
-          @getphonenumber="thirdLogin('wechat', $event)"
-          class="ss-reset-button auto-login-btn"
+          v-if="sheep.$platform.name !== 'WechatMiniProgram'"
+          class="ss-reset-button type-btn"
+          @tap="showAuthModal('smsRegister')"
         >
-          <image
-            class="auto-login-img"
-            :src="sheep.$url.static('/static/img/shop/platform/wechat.png')"
-          ></image>
+          立即注册
         </button>
 
         <!-- 公众号|App微信登录 -->
@@ -74,6 +89,7 @@
       <view
         v-if="['accountLogin', 'smsLogin', 'smsRegister'].includes(authType)"
         class="agreement-box ss-flex ss-row-center"
+        :class="{ shake: currentProtocol }"
       >
         <label class="radio ss-flex ss-col-center" @tap="onChange">
           <radio
@@ -106,7 +122,7 @@
 </template>
 
 <script setup>
-  import { computed, reactive } from 'vue';
+  import { computed, reactive, ref } from 'vue';
   import sheep from '@/sheep';
   import accountLogin from './components/account-login.vue';
   import smsLogin from './components/sms-login.vue';
@@ -115,7 +131,8 @@
   import changeMobile from './components/change-mobile.vue';
   import changePasswrod from './components/change-password.vue';
   import changeUsername from './components/change-username.vue';
-  import { closeAuthModal } from '@/sheep/hooks/useModal';
+  import mpAuthorization from './components/mp-authorization.vue';
+  import { closeAuthModal, showAuthModal } from '@/sheep/hooks/useModal';
 
   const appInfo = computed(() => sheep.$store('app').info);
 
@@ -127,6 +144,8 @@
     protocol: false,
   });
 
+  const currentProtocol = ref(false);
+
   //勾选协议
   function onChange() {
     state.protocol = !state.protocol;
@@ -141,16 +160,39 @@
     });
   }
 
+  // 点击登录/注册事件
+  function onConfirm(e) {
+    currentProtocol.value = e;
+    setTimeout(() => {
+      currentProtocol.value = false;
+    }, 1000);
+  }
+
   // 第三方授权登陆
-  const thirdLogin = async (provider, event = null) => {
+  const thirdLogin = async (provider) => {
     if (!state.protocol) {
+      currentProtocol.value = true;
+      setTimeout(() => {
+        currentProtocol.value = false;
+      }, 1000);
       sheep.$helper.toast('请勾选同意');
       return;
     }
-    const loginRes = await sheep.$platform.useProvider(provider).login(event?.detail || null);
+    const loginRes = await sheep.$platform.useProvider(provider).login();
     if (loginRes) {
       closeAuthModal();
       const userInfo = await sheep.$store('user').getInfo();
+      // 触发小程序授权信息弹框
+      // #ifdef MP-WEIXIN
+      if (userInfo.third_oauth.length > 0) {
+        const mpThirdOauthInfo = userInfo.third_oauth.find(
+          (item) => item.platform === 'miniProgram',
+        );
+        if (mpThirdOauthInfo && !mpThirdOauthInfo.nickname) {
+          showAuthModal('mpAuthorization');
+        }
+      }
+      // #endif
     }
   };
 </script>
@@ -158,6 +200,54 @@
 <style lang="scss" scoped>
   @import './index.scss';
 
+  .shake {
+    animation: shake 0.05s linear 4 alternate;
+  }
+
+  @keyframes shake {
+    from {
+      transform: translateX(-10rpx);
+    }
+    to {
+      transform: translateX(10rpx);
+    }
+  }
+
+  .register-box {
+    position: relative;
+    justify-content: center;
+    .register-btn {
+      color: #999999;
+      font-size: 30rpx;
+      font-weight: 500;
+    }
+    .register-title {
+      color: #999999;
+      font-size: 30rpx;
+      font-weight: 400;
+      margin-right: 24rpx;
+    }
+    .or-title {
+      margin: 0 16rpx;
+      color: #999999;
+      font-size: 30rpx;
+      font-weight: 400;
+    }
+    .login-btn {
+      color: var(--ui-BG-Main);
+      font-size: 30rpx;
+      font-weight: 500;
+    }
+    .circle {
+      position: absolute;
+      right: 0rpx;
+      top: 18rpx;
+      width: 8rpx;
+      height: 8rpx;
+      border-radius: 8rpx;
+      background: var(--ui-BG-Main);
+    }
+  }
   .safe-box {
     height: calc(constant(safe-area-inset-bottom) / 5 * 3);
     height: calc(env(safe-area-inset-bottom) / 5 * 3);

+ 39 - 12
sheep/platform/provider/wechat/miniProgram.js

@@ -17,8 +17,32 @@ function load() {
   getSubscribeTemplate();
 }
 
-// 微信小程序授权登陆
-const login = async (e) => {
+// 微信小程序静默授权登陆 TODO-ldh: code > 0 问题 改为error
+const login = async () => {
+  return new Promise(async (resolve, reject) => {
+    const { error } = await third.wechat.login({
+      platform: 'miniProgram',
+      shareInfo: uni.getStorageSync('shareLog') || {},
+      payload: encodeURIComponent(
+        JSON.stringify({
+          sessionId: uni.getStorageSync('sessionId'),
+        }),
+      ),
+    });
+
+    if (error === 0) {
+      resolve(true);
+    }
+
+    if (error === -1) {
+      getSessionId(false);
+    }
+    resolve(false);
+  });
+};
+
+// 微信小程序手机号授权登陆
+const mobileLogin = async (e) => {
   return new Promise(async (resolve, reject) => {
     if (e.errMsg !== 'getPhoneNumber:ok') {
       resolve(false);
@@ -43,7 +67,7 @@ const login = async (e) => {
     }
 
     if (error === -1) {
-      getSessionId();
+      getSessionId(false);
     }
     resolve(false);
   });
@@ -62,7 +86,7 @@ const bind = () => {
     });
 
     if (loginRes.error === -1) {
-      getSessionId();
+      getSessionId(false);
     } else if (loginRes.error === 0) {
       resolve(true);
     } else {
@@ -76,27 +100,30 @@ const unbind = async () => {
   const { error } = await third.wechat.unbind({
     platform: 'miniProgram',
   });
-  return Promise.resolve(!error);
+  return !error;
 };
 
 // 获取最新sessionId
-const getSessionId = async () => {
+const getSessionId = async (auto_login = null) => {
   // 获取code
-  let code = '';
+  let codeStr = '';
   const loginResult = await uni.login();
   if (loginResult.errMsg === 'login:ok') {
-    code = loginResult.code;
+    codeStr = loginResult.code;
   } else {
-    getSessionId();
+    getSessionId(auto_login);
     return false;
   }
+  if(auto_login === null) {
+    auto_login = !!($store('app').platform.auto_login && !$store('user').isLogin);
+  }
 
   const { error, data } = await third.wechat.getSessionId({
     platform: 'miniProgram',
     payload: encodeURIComponent(
       JSON.stringify({
-        code,
-        auto_login: !!($store('app').platform.auto_login && !$store('user').isLogin),
+        code: codeStr,
+        auto_login,
       }),
     ),
   });
@@ -170,7 +197,7 @@ const bindUserPhoneNumber = (e) => {
       platform: 'miniProgram',
       payload: encodeURIComponent(
         JSON.stringify({
-          code: e.code,
+          sessionId: uni.getStorageSync('sessionId'),
           iv: e.iv,
           encryptedData: e.encryptedData,
         }),