feat: 登录的时候上传头像和微信名
This commit is contained in:
parent
0baa476aee
commit
c25e4ed02c
@ -40,10 +40,19 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="auth-title">申请获取以下权限</view>
|
||||
<view class="auth-subtitle">获得你的公开信息(昵称、头像等)</view>
|
||||
<view class="auth-subtitle">获得你的公开信息(昵称、头像、手机号等)</view>
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<view class="login-btn">
|
||||
<button class="button" open-type="getPhoneNumber" @getphonenumber="handleLoginWithPhone" @click="clickPhoneNumber" :class="{ disabled }">
|
||||
一键登录
|
||||
</button>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-WEIXIN -->
|
||||
<view class="login-btn">
|
||||
<view class="button" :class="{ disabled }" @click="handleLogin()">一键登录</view>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<view class="no-login-btn">
|
||||
<view class="button" @click="handleCancel()">暂不登录</view>
|
||||
</view>
|
||||
@ -53,10 +62,9 @@
|
||||
|
||||
<script>
|
||||
import store from '@/store'
|
||||
import * as LoginApi from '@/api/login'
|
||||
import * as UploadApi from '@/api/upload'
|
||||
import AvatarImage from '@/components/avatar-image'
|
||||
import * as Verify from '@/utils/verify'
|
||||
import * as OrderApi from '@/api/order'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -74,17 +82,66 @@
|
||||
tempFile: undefined,
|
||||
// 表单数据
|
||||
form: {
|
||||
avatarId: null,
|
||||
nickName: ''
|
||||
},
|
||||
// 手机号加密数据
|
||||
phoneEncryptedData: '',
|
||||
phoneIv: '',
|
||||
// 微信小程序登录凭证 (code)
|
||||
// 提交到后端,用于换取openid
|
||||
code: ''
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 一键登录按钮点击事件
|
||||
// 一键登录按钮点击事件(非微信小程序环境)
|
||||
handleLogin() {
|
||||
this.onAuthSuccess({})
|
||||
},
|
||||
|
||||
// 按钮点击事件: 获取微信手机号按钮
|
||||
// 实现目的: 在getphonenumber事件触发之前获取微信登录code
|
||||
// 因为如果在getphonenumber事件中获取code的话,提交到后端的encryptedData会存在解密不了的情况
|
||||
async clickPhoneNumber() {
|
||||
// #ifdef MP-WEIXIN
|
||||
if (!this.disabled) {
|
||||
this.code = await this.getCode()
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
|
||||
// 微信小程序一键登录(带手机号授权)
|
||||
async handleLoginWithPhone({ detail }) {
|
||||
const app = this
|
||||
// #ifdef MP-WEIXIN
|
||||
// 处理手机号授权
|
||||
if (detail.errMsg === 'getPhoneNumber:ok') {
|
||||
// 获取手机号成功
|
||||
app.phoneEncryptedData = detail.encryptedData
|
||||
app.phoneIv = detail.iv
|
||||
console.log('获取手机号成功', {
|
||||
hasEncryptedData: !!detail.encryptedData,
|
||||
hasIv: !!detail.iv,
|
||||
hasCode: !!app.code
|
||||
})
|
||||
|
||||
// 准备用户信息数据,包含手机号加密信息
|
||||
let userInfo = {
|
||||
phoneEncryptedData: detail.encryptedData,
|
||||
phoneIv: detail.iv,
|
||||
nickName: '',
|
||||
avatarUrl: ''
|
||||
}
|
||||
|
||||
// 执行登录,将手机号信息传递给后端
|
||||
app.onAuthSuccess(userInfo)
|
||||
} else {
|
||||
// 用户拒绝授权手机号
|
||||
console.log('用户拒绝授权手机号', detail)
|
||||
app.$toast('为了更好的体验,请授权手机号再登录')
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
// 授权成功事件
|
||||
// 这里分为两个逻辑:
|
||||
// 1.将code和userInfo提交到后端,如果存在该用户 则实现自动登录,无需再填写手机号
|
||||
@ -92,22 +149,51 @@
|
||||
// 3.如果后端报错了, 则显示错误信息
|
||||
async onAuthSuccess(userInfo) {
|
||||
const app = this
|
||||
// 如果还没有获取code,则获取code
|
||||
// 提交到后端
|
||||
const code = await app.getCode()
|
||||
store.dispatch('LoginMpWx', { code })
|
||||
if (!app.code) {
|
||||
app.code = await app.getCode()
|
||||
}
|
||||
|
||||
// 准备登录数据,包含手机号、昵称和头像信息
|
||||
const loginData = {
|
||||
code: app.code,
|
||||
phoneEncryptedData: userInfo.phoneEncryptedData || '',
|
||||
phoneIv: userInfo.phoneIv || '',
|
||||
nickName: userInfo.nickName || '',
|
||||
avatarUrl: userInfo.avatarUrl || ''
|
||||
}
|
||||
|
||||
console.log('登录数据:', {
|
||||
hasCode: !!loginData.code,
|
||||
hasPhoneNumber: !!(loginData.phoneEncryptedData && loginData.phoneIv),
|
||||
nickName: loginData.nickName,
|
||||
hasAvatar: !!(loginData.avatarUrl)
|
||||
})
|
||||
|
||||
// 按钮禁用
|
||||
app.disabled = true
|
||||
|
||||
store.dispatch('LoginMpWx', loginData)
|
||||
.then(result => {
|
||||
// 一键登录成功
|
||||
app.$toast('登录成功')
|
||||
// 相应全局事件订阅: 刷新上级页面数据
|
||||
uni.$emit('syncRefresh', true)
|
||||
// 跳转回原页面
|
||||
setTimeout(() => app.onNavigateBack(), 2000)
|
||||
app.disabled = false
|
||||
if (!result.data.buyer.avatarUrl) {
|
||||
app.isPersonal = true
|
||||
} else {
|
||||
app.$toast('登录成功')
|
||||
uni.$emit('syncRefresh', true)
|
||||
setTimeout(() => app.onNavigateBack(), 2000)
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
const resultData = err.result.data
|
||||
const resultData = err.result?.data || {}
|
||||
// 判断还需绑定手机号
|
||||
if (resultData.isBindMobile) {
|
||||
app.onEmitSuccess(userInfo)
|
||||
} else {
|
||||
// 其他错误,恢复按钮状态
|
||||
app.disabled = false
|
||||
app.code = '' // 重置code,下次重新获取
|
||||
}
|
||||
})
|
||||
},
|
||||
@ -145,8 +231,64 @@
|
||||
onChooseAvatar({ detail }) {
|
||||
// #ifdef MP-WEIXIN
|
||||
const app = this
|
||||
app.avatarUrl = detail.avatarUrl
|
||||
app.tempFile = { path: app.avatarUrl }
|
||||
console.log('onChooseAvatar', detail)
|
||||
|
||||
// chooseAvatar 返回的临时文件路径在开发者工具中可能无法直接访问
|
||||
// 需要将临时文件保存到小程序文件系统中
|
||||
const tempFilePath = detail.avatarUrl
|
||||
|
||||
// 先显示临时路径(用于预览)
|
||||
app.avatarUrl = tempFilePath
|
||||
|
||||
// 将临时文件保存到小程序文件系统
|
||||
// uni.saveFile 会将临时文件保存到小程序的文件系统中,返回一个可用的文件路径
|
||||
uni.saveFile({
|
||||
tempFilePath: tempFilePath,
|
||||
success: (res) => {
|
||||
// 保存成功,使用保存后的文件路径
|
||||
const savedFilePath = res.savedFilePath
|
||||
console.log('头像文件保存成功', savedFilePath)
|
||||
app.avatarUrl = savedFilePath
|
||||
app.tempFile = { path: savedFilePath }
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('头像文件保存失败', err)
|
||||
// 如果保存失败,尝试使用文件系统管理器复制文件
|
||||
// 在开发者工具中,临时文件可能无法访问,但真机上通常可以直接使用
|
||||
try {
|
||||
const fs = wx.getFileSystemManager()
|
||||
// 使用小程序的用户数据目录(如果可用)
|
||||
const userDataPath = wx.env && wx.env.USER_DATA_PATH
|
||||
if (userDataPath) {
|
||||
const timestamp = Date.now()
|
||||
const random = Math.random().toString(36).substring(2, 8)
|
||||
const destPath = `${userDataPath}/avatar_${timestamp}_${random}.jpg`
|
||||
|
||||
fs.copyFile({
|
||||
srcPath: tempFilePath,
|
||||
destPath: destPath,
|
||||
success: (copyRes) => {
|
||||
console.log('头像文件复制成功', destPath)
|
||||
app.avatarUrl = destPath
|
||||
app.tempFile = { path: destPath }
|
||||
},
|
||||
fail: (copyErr) => {
|
||||
console.error('头像文件复制也失败', copyErr)
|
||||
// 最后尝试直接使用临时路径(真机上通常可用)
|
||||
app.tempFile = { path: tempFilePath }
|
||||
}
|
||||
})
|
||||
} else {
|
||||
// 如果无法获取文件目录,直接使用临时路径(真机上通常可用)
|
||||
app.tempFile = { path: tempFilePath }
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('文件处理异常', e)
|
||||
// 最后尝试直接使用临时路径(真机上通常可用)
|
||||
app.tempFile = { path: tempFilePath }
|
||||
}
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
|
||||
@ -168,9 +310,9 @@
|
||||
// 上传图片
|
||||
uploadFile() {
|
||||
const app = this
|
||||
return UploadApi.image([app.tempFile], false)
|
||||
.then(fileIds => {
|
||||
app.form.avatarId = fileIds[0]
|
||||
return OrderApi.apiUploadFile([app.tempFile])
|
||||
.then(res => {
|
||||
app.form.avatarUrl = res[0].data[0].url
|
||||
app.tempFile = null
|
||||
return true
|
||||
})
|
||||
@ -199,7 +341,7 @@
|
||||
return
|
||||
}
|
||||
// 提交到后端
|
||||
app.onAuthSuccess({ nickName: app.form.nickName, avatarId: app.form.avatarId })
|
||||
app.onAuthSuccess({ nickName: app.form.nickName, avatarUrl: app.form.avatarUrl })
|
||||
},
|
||||
|
||||
// 将oauth提交给父级
|
||||
@ -350,11 +492,19 @@
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: none;
|
||||
padding: 0;
|
||||
line-height: 86rpx;
|
||||
|
||||
// 禁用按钮
|
||||
&.disabled {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
// 微信小程序button组件样式重置
|
||||
&::after {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user