c

crazyu

V1

2022/11/11阅读:50主题:默认主题

保姆级微信手动填写微信昵称、头像接入

近期由于微信小程序的获取用户头像、昵称调整导致获取用户信息失败,所以记录下适合使用。

1.登录页面改版

登录.jpg
登录.jpg

2.用户头像、昵称获取完整思路

1.html布局 按钮 open-type="chooseAvatar"、 @chooseavatar(选择头像的回调)

  • 注意点:<input type="nickname" name="nickname" class="weui-input" placeholder="请输入昵称" />由于设置@change、@blur事件都无法获取用户选择昵称或者是输入的昵称,遂通过form表单的方式进行获取用户的昵称
  • submit 获取到用户昵称或者是头像进行登录
<form @submit="login">
  <view class="item">
    <view class="label">头像</view>
    <view class="value">
     <button class="avatar-wrapper" name="avatar" 
        open-type="chooseAvatar" @chooseavatar="handleRouter"
     >
     </button>
    </view>
 </view>
 <view class="item">
    <view class="label"> 昵称</view>
        <view class="value">
          <input type="nickname" name="nickname" 
            v-model="username" class="weui-input" placeholder="请输入昵称" />
        </view>
    </view>
    <view class="tip">
    <view class="choose">
        <u-checkbox-group
            @change="checkboxChange"
            class="checkbox_wrapper"
            v-model="choose"
        >
            <u-checkbox
                v-for="(item, index) of list"
                :key="index"
                activeColor="red"
                :name="item.name"
                value="cb"
            >
        </u-checkbox>
        </u-checkbox-group>
        请阅读并勾选<text @click="navPrice">《用户协议》</text>
    </view>
    </view>
    <button class="login_btn" form-type="submit">微信一键登录</button>
</form>

// js
handleRouter(e) {
    const _this = this
    this.avatarUrl = e.detail.avatarUrl
}

3.真实的登录逻辑

  • 由于拿到的用户头像是临时路径生成的地址,为了能够防止失效,遂将临时图片上传到服务器, 方法有两种:
  1. 通过uni.download下载文件,然后进行文件上传;
  2. 通过提供的文件系统api 保存图片
    但是在实际使用的时候,uni.download下载临时图片,微信开发者不会有问题,但是真机会报错:[dowloadFileLfail url scheme is invalid],查询资料发现是因为下载的地址需要在微信设置白名单,否则就会报错,但是当前的文件是临时路径文件生成的,无固定的域名信息,遂此方法不合适;然后尝试文件系统API,并且实践后在真机上正常运行
// 通过文件系统API下载图片代码如下:
const fs = uni.getFileSystemManager()
fs.saveFile({
  tempFilePath: this.avatarUrl, // 传入一个本地临时文件路径
  success(res) {
    console.log(res.savedFilePath) // res.savedFilePath 为一个本地缓存文件路径
    const tmp = res.savedFilePath
    // _this.uploadUserAvater(tmp)
  }
})
  • 文件上传的时机:
  1. 在用户点击 “微信一键登录” 按钮时登录成功之后上传,然后在更新用户信息,在进行跳转页面但是此方法在登录的时候链路太长,遂放弃
  2. 在微信用户点击默认头像按钮的时候,进行上传(最后也是选择此方法,减少在登录时的链路,此时上传需要后台支持接口无需token验证,因为用户并未登录)
  3. 在用户点击“微信一键登录”的按钮时,将头像上传后的服务器地址更新到用户信息里面,

4.完整的代码如下:

<template>
<view class="wrapper">
 <image class="bg" src="../../static/denglu.png" mode=""></image>
   <view class="content">
     <image class="logo_title" src="../../static/title.png" mode="aspectFit"></image>
      <view class="login">
          <view class="operate">
             <view class="header">
                 <text class="title">XXXX</text> 申请
             </view>
             <view class="nickname">
                 获取你的昵称、头像
             </view>
             <form @submit="login">
                 <view class="item">
                     <view class="label"> 头像  </view>
                     <view class="value">
                         <button class="avatar-wrapper" name="avatar" open-type="chooseAvatar" @chooseavatar="handleRouter">
                             <image class="avatar" :src="avatarUrl"></image>
                         </button>
                     </view>
                 </view>
                 <view class="item">
                     <view class="label"> 昵称 </view>
                     <view class="value">
                         <input type="nickname" name="nickname" v-model="username" class="weui-input" placeholder="请输入昵称" />
                     </view>
                 </view>
                 <view class="tip">
                     <view class="choose">
                         <u-checkbox-group
                             @change="checkboxChange"
                             class="checkbox_wrapper"
                             v-model="choose"
                         >
                             <u-checkbox
                                 v-for="(item, index) of list"
                                 :key="index"
                                 activeColor="red"
                                 :name="item.name"
                                 value="cb"
                             >
                         </u-checkbox>
                         </u-checkbox-group>
                         请阅读并勾选<text @click="navPrice">《用户协议》</text>
                     </view>
                 </view>
                 <button class="login_btn" form-type="submit">微信一键登录</button>
             </form>
         </view>
     </view>
   </view>
 </view>
</template>

<script>
import {authoriztion} from '@/api/login.js'
import { getUserInfo, updateUserInfo } from '@/api/center.js'
import { getToken, setToken } from '@/utils/auth.js'
import { host } from '@/utils/request.js'
export default{
data () {
 return {
     choose: ['选择'],
     avatarUrl: 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0',
     list: [
         {
             name: '选择',
             checked: true
         }
     ],
     code: '',
     username: ''
 }
},
mounted() {
 const _this = this;
 uni.login({
   success(even) {
     if (even.code) {
       _this.code=even.code;
   }
 }
})
},
methods: {
 checkboxChange (v) {
     console.log('v', v)
     this.choose = v
 },
 async fetchUserInfo () {
     const res = await getUserInfo()
     uni.hideLoading()
     if (res.data.errcode == 0) {
         const userInfo = res.data.data
         this.userInfo = userInfo
         if (userInfo.DutyType == 2) {
             uni.redirectTo({
                 url:'/pages/friends/friends'
             })
         } else {
             uni.redirectTo({
                 url: '/pages/index/index'
             })
         }
     } else {
         uni.showToast({
             title: res.errMsg
         })
     }
 },
 login (e) {
     const _this = this
     const nickName = e.detail.value.nickname
     if (!this.avatarUrl) {
         uni.showToast({
             title: '请授权头像',
             icon:"none"
         })
         return
     }
     if (!nickName) {
         uni.showToast({
             title: '请授权昵称',
             icon:"none"
         })
         return
     }
     if (!this.choose.length) {
         uni.showToast({
             title: '请勾选协议',
             icon:"none"
         })
         return
     }
     uni.showLoading({
         title: '加载中'
     })
     authoriztion({
         "js_code": _this.code,
         "photo": this.avatarUrl,
         "username": nickName,
         "gender": 0
     }).then(even => {
         console.log('even', even)
         if (even.data.errcode == 0) {
             setToken(even.data.data)
             uni.setStorageSync("token", even.data.data)
             _this.fetchUserInfo()
         }
     })
 },
 uploadUserAvater (avater) {
     const _this = this
     uni.uploadFile({
       url:host +'api/OrderImg/Upload', //仅为示例,非真实的接口地址
       filePath: avater,
       name: 'file',
       header: {
         Authorization: getToken(),
       },
       success: (res) => {
         console.log('上传结果', res)
         uni.hideLoading()
         const response = JSON.parse(res.data)
         if (response.errcode == 0) {
             _this.avatarUrl = response.data
         } else {
             uni.showToast({
                 title: response.errMsg
             })
         }
       },
     })
 },
 handleRouter(e) {
     const _this = this
     this.avatarUrl = e.detail.avatarUrl
     _this.$nextTick(() => {
         uni.showLoading({
             title: '加载中'
         })
         const fs = uni.getFileSystemManager()
         fs.saveFile({
           tempFilePath: this.avatarUrl, // 传入一个本地临时文件路径
           success(res) {
             console.log(res.savedFilePath) // res.savedFilePath 为一个本地缓存文件路径
             const tmp = res.savedFilePath
             _this.uploadUserAvater(tmp)
           }
         })
         // uni.downloadFile({
         //  url: _this.avatarUrl, //仅为示例,并非真实的资源
         //  success: (res) => {
         //   if (res.statusCode === 200) {
         //    console.log('下载成功====', res);
         //    _this.uploadUserAvater(res.tempFilePath)
         //   }
         //  }
         // })
     })
 }
}
}
</script>

<style lang="scss" scoped>
.avatar-wrapper{
 display: inline-flex;
 justify-content: center;
 align-items: center;
 padding: 0;
}
.wrapper{
 .bg{
     position: absolute;
     top: 0;
     left: 0;
     width: 100vw;
     height: 100vh;
     z-index: -1;
 }
 .content{
     margin: 0 24rpx 0 24rpx;
     display: flex;
     justify-content: center;
     align-items: center;
     flex-direction: column;
     .logo_title{
         width: 400rpx;
         height: 128rpx;
         margin-top: 160rpx;
         margin-left: 50%;
         transform: translateX(-50%);
     }
     .login{
         border-radius: 10px 10px 10px 10px;
         width: 100%;
         padding: 40rpx 0 50rpx 0;
         box-sizing: border-box;
         .loginItem{
             margin-bottom: 60rpx;
             display: flex;
             flex-direction: row;
             flex-wrap: nowrap;
             align-items: center;
             .icon{
                 width: 70rpx;
                 height: 60rpx;
             }
             .user{
                 background: rgba(249,249,255,0.93);
                 border-radius: 25px 25px 25px 25px;
                 opacity: 1;
                 border: 2px solid #75F9FD;
                 height: 70rpx;
                 line-height: 71r;
                 margin-left: 20rpx;
                 width: 100%;
                 padding: 0 40rpx;
                 .pcs{

                 }
             }
         }
         .operate{
             width: 100%;
             margin-top: 20rpx;
             color: white;
             display: flex;
             flex-direction: column;
             background: white;
             padding: 40rpx;
             border-radius: 30rpx;
             box-sizing: border-box;
             .header{
                 color: #333;
                 .title{
                     font-weight: bold;
                     margin-right: 30rpx;
                 }
             }
             .nickname{
                 color: #333;
                 font-size: 32rpx;
                 font-weight: bold;
                 margin-top: 40rpx;
                 margin-bottom: 50rpx;
             }
             .item{
                 display: flex;
                 flex-direction: row;
                 flex-wrap: nowrap;
                 height: 90rpx;
                 margin-bottom: 30rpx;
                 .label{
                     width: 100rpx;
                     color: black;
                     display: flex;
                     justify-content: center;
                     align-items: center;
                 }
                 .value{
                     flex: 1;
                     display: flex;
                     justify-content: center;
                     color: black;
                     .avatar-wrapper{
                         width: 80rpx;
                         height: 80rpx;
                         .avatar{
                             width: 80rpx;
                             height: 80rpx;
                         }
                     }
                     .weui-input{
                         background-color: white;
                         width: 80%;
                         border-radius: 10rpx;
                         padding: 20rpx;
                         border-bottom: 2rpx solid #ccc;
                     }
                 }
             }
             .login_btn{
                 background: linear-gradient(180deg, rgba(117, 249, 253, 0.93) 0%, rgba(184, 134, 248, 0.93) 100%);
                 border-radius: 25px;
                 color: #FFFFFF;
                 margin-top: 40rpx;
                 width: 100%;
             }
             .tip{
                 color: black;
                 display: flex;
                 flex-direction: column;
                 width: 100%;
                 justify-content: center;
                 align-items: center;
                 .wechat{
                         width: 80rpx;
                         height: 80rpx;
                 }
                 .choose{
                     margin-top: 10rpx;
                     display: flex;
                     flex-direction: row;
                     flex-wrap: nowrap;
                     align-items: center;
                     .checkbox_wrapper{

                     }
                 }
             }
         }
     }
 }
 
}
</style>

写在最后

我是crazyu,一位前端开发工程师。

  • 文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎点赞和关注😊
  • 本文首发于微信公众号:crazyu 前端,未经许可禁止转载

分类:

前端

标签:

前端

作者介绍

c
crazyu
V1