添加手机号授权登陆

This commit is contained in:
lewis 2025-09-06 15:43:36 +08:00
parent ee9c32bf7a
commit 2c654d38ee
6 changed files with 182 additions and 17 deletions

6
env/.env vendored
View File

@ -28,9 +28,9 @@ VITE_SERVER_BASEURL__WEIXIN_DEVELOP = 'https://test.data-middle.lihaink.cn'
VITE_SERVER_BASEURL__WEIXIN_TRIAL = 'https://test.data-middle.lihaink.cn' VITE_SERVER_BASEURL__WEIXIN_TRIAL = 'https://test.data-middle.lihaink.cn'
VITE_SERVER_BASEURL__WEIXIN_RELEASE = 'https://test.data-middle.lihaink.cn' VITE_SERVER_BASEURL__WEIXIN_RELEASE = 'https://test.data-middle.lihaink.cn'
VITE_UPLOAD_BASEURL__WEIXIN_DEVELOP = 'https://test.data-middle.lihaink.cn/upload' VITE_UPLOAD_BASEURL__WEIXIN_DEVELOP = 'https://test.data-middle.lihaink.cn/api/upload/image'
VITE_UPLOAD_BASEURL__WEIXIN_TRIAL = 'https://test.data-middle.lihaink.cn/upload' VITE_UPLOAD_BASEURL__WEIXIN_TRIAL = 'https://test.data-middle.lihaink.cn/api/upload/image'
VITE_UPLOAD_BASEURL__WEIXIN_RELEASE = 'https://test.data-middle.lihaink.cn/upload' VITE_UPLOAD_BASEURL__WEIXIN_RELEASE = 'https://test.data-middle.lihaink.cn/api/upload/image'
# h5是否需要配置代理 # h5是否需要配置代理
VITE_APP_PROXY=true VITE_APP_PROXY=true

View File

@ -92,3 +92,7 @@ export function wxLogin(data: { code: string }) {
// export function routineLoginApi(data: { code: string }) { // export function routineLoginApi(data: { code: string }) {
// return http.post('/api/auth/routineLogin', data) // return http.post('/api/auth/routineLogin', data)
// } // }
export function phoneLogin(data) {
return http.post('/api/auth/phoneLogin', data)
}

View File

@ -7,14 +7,117 @@
} }
</route> </route>
<template>
<view class=""></view>
</template>
<script lang="ts" setup> <script lang="ts" setup>
// import { useUserStore } from '@/store'
import { toast } from '@/utils/toast'
const lastPage = ref('')
onMounted(() => {
uni.hideTabBar()
const pages = getCurrentPages()
const route = pages[pages.length - 2].$page.fullPath
lastPage.value = route
})
const userStore = useUserStore()
async function decryptPhoneNumber(e) {
if (!e.detail.iv) {
toast.error('取消登录')
return
}
const res = await userStore.wxPhoneLogin(e.detail.iv, e.detail.encryptedData)
if (res.code === 1) {
toast.success('登录成功')
setTimeout(() => {
userStore.clearLastPage()
if (lastPage.value) {
let method
const indexPat = [
'/pages/index/index',
'/pages/about/index',
'/pages/service/index',
'/pages/my/index',
]
if (indexPat.includes(lastPage.value)) {
method = 'switchTab'
} else {
method = 'navigateTo'
}
if (lastPage.value === '/pages/login/login') {
uni.switchTab({
url: '/pages/index/index',
})
return
}
uni[method]({
url: lastPage.value,
})
} else {
uni.navigateBack({
delta: 2,
})
}
}, 1500)
} else {
toast.error(res.msg)
}
}
</script> </script>
<template>
<view class="fly-login">
<view class="fly-login-mask" />
<view class="fly-login-content px-4">
<view class="m-10 text-center">
<button
type="primary"
custom-class="font-bold font-size-4"
block
open-type="getPhoneNumber"
@getphonenumber="decryptPhoneNumber"
>
<text class="font-size-4 color-white font-bold text-shadow">手机号快捷登录</text>
</button>
</view>
<view class="text-center">
<text class="font-size-4 color-white font-bold text-shadow" @click="onClose">暂不登录</text>
</view>
<view />
</view>
</view>
</template>
<style lang="scss" scoped> <style lang="scss" scoped>
// .fly-login {
background: url(https://imgs.design006.com/201812/Design006_Nh8kwSNRfZ.jpg);
background-size: cover; /* 保持图片宽高比的同时覆盖整个背景区域 */
background-position: center; /* 将背景图片居中 */
background-repeat: no-repeat; /* 防止背景图片重复 */
width: 100%;
height: 100%;
display: flex;
bottom: 0;
z-index: 999;
position: fixed;
inset: 0;
.fly-login-mask {
position: fixed;
inset: 0;
background-color: rgb(0 0 0 / 30%);
}
.fly-login-content {
position: fixed;
right: 0;
bottom: var(--window-bottom);
left: 0;
top: 50vh;
// background-color: #fff;
border-top-left-radius: 16px;
border-top-right-radius: 16px;
}
}
</style> </style>

View File

@ -41,14 +41,43 @@ function getUserInfo() {
} }
function handleSubmit() { function handleSubmit() {
if (formData.user_id == '') {
uni.showToast({
title: '请选择村民',
icon: 'error',
})
return
}
if (formData.store_name == '') {
uni.showToast({
title: '请填写商品名称',
icon: 'error',
})
return
}
if (formData.number == '') {
uni.showToast({
title: '请填写数量',
icon: 'error',
})
return
}
if (formData.price == '') {
uni.showToast({
title: '请填写单价',
icon: 'error',
})
return
}
commitProduct(formData).then((res) => { commitProduct(formData).then((res) => {
if (res.code == 1) { if (res.code === 1) {
uni.showToast({ uni.showToast({
title: '上传成功', title: '上传成功',
}) })
} else { } else {
uni.showToast({ uni.showToast({
title: res.data.msg, title: res.msg,
icon: 'error',
}) })
} }
}) })
@ -62,6 +91,11 @@ function uploadSuccess(res) {
const response = JSON.parse(res.file.response) const response = JSON.parse(res.file.response)
if (response.code === 1) { if (response.code === 1) {
formData.image.push(response.data.uri) formData.image.push(response.data.uri)
} else {
uni.showToast({
title: response.msg,
icon: 'error',
})
} }
} }

View File

@ -1,15 +1,17 @@
import type { IUserInfoVo } from '@/api/login.typings' import type { IUserInfoVo } from '@/api/login.typings'
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { ref } from 'vue' import { ref } from 'vue'
import { getEnvBaseUrl } from '@/utils'
import { import {
getUserInfo as _getUserInfo, getUserInfo as _getUserInfo,
login as _login, login as _login,
logout as _logout, logout as _logout,
wxLogin as _wxLogin, wxLogin as _wxLogin,
getWxCode, getWxCode,
phoneLogin,
} from '@/api/login' } from '@/api/login'
import { getEnvBaseUrl } from '@/utils'
import { toast } from '@/utils/toast' import { toast } from '@/utils/toast'
const baseUrl = getEnvBaseUrl() const baseUrl = getEnvBaseUrl()
// 初始化状态 // 初始化状态
const userInfoState: IUserInfoVo = { const userInfoState: IUserInfoVo = {
@ -32,11 +34,11 @@ export const useUserStore = defineStore(
if (!val.avatar) { if (!val.avatar) {
val.avatar = userInfoState.avatar val.avatar = userInfoState.avatar
} else { } else {
val.avatar = baseUrl + val.avatar //地址拼接 val.avatar = baseUrl + val.avatar // 地址拼接
// val.avatar = 'https://oss.laf.run/ukw0y1-site/avatar.jpg?feige' // val.avatar = 'https://oss.laf.run/ukw0y1-site/avatar.jpg?feige'
} }
//判断是否设置村庄 // 判断是否设置村庄
val.isset = userInfoState.village ? true : false val.isset = !!userInfoState.village
userInfo.value = val userInfo.value = val
} }
const setUserAvatar = (avatar: string) => { const setUserAvatar = (avatar: string) => {
@ -105,6 +107,21 @@ export const useUserStore = defineStore(
return res return res
} }
const wxPhoneLogin = async (iv, encryptedData) => {
const code = await getWxCode()
const data = {
iv,
code: code.code,
encryptedData,
}
const res = await phoneLogin(data)
const userInfo = res.data
setUserInfo(userInfo)
uni.setStorageSync('userInfo', userInfo)
uni.setStorageSync('token', userInfo.token)
return res
}
return { return {
userInfo, userInfo,
setUserInfo, setUserInfo,
@ -113,6 +130,7 @@ export const useUserStore = defineStore(
getUserInfo, getUserInfo,
setUserAvatar, setUserAvatar,
logout, logout,
wxPhoneLogin,
} }
}, },
{ {

View File

@ -18,8 +18,14 @@ export function http<T>(options: CustomRequestOptions) {
} else if (res.statusCode === 401) { } else if (res.statusCode === 401) {
// 401错误 -> 清理用户信息,跳转到登录页 // 401错误 -> 清理用户信息,跳转到登录页
// userStore.clearUserInfo() // userStore.clearUserInfo()
// uni.navigateTo({ url: '/pages/login/login' }) uni.showToast({
reject(res) icon: 'none',
title: (res.data as IResData<T>).msg || '请登录',
})
setTimeout(() => {
uni.navigateTo({ url: '/pages/login/login' })
}, 1500)
// reject(res)
} else { } else {
// 其他错误 -> 根据后端错误信息轻提示 // 其他错误 -> 根据后端错误信息轻提示
!options.hideErrorToast && !options.hideErrorToast &&