feat: 微信小程序登录改造(手机号授权 + API前缀改为/mp-api + 隐私协议检查)
This commit is contained in:
+12
@@ -3,6 +3,18 @@ import { onLaunch } from '@dcloudio/uni-app'
|
|||||||
import { useUserStore } from './store/user'
|
import { useUserStore } from './store/user'
|
||||||
|
|
||||||
onLaunch(() => {
|
onLaunch(() => {
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
wx.getPrivacySetting({
|
||||||
|
success: (res: any) => {
|
||||||
|
if (res.needAuthorization) {
|
||||||
|
uni.setStorageSync('needPrivacy', true)
|
||||||
|
} else {
|
||||||
|
uni.removeStorageSync('needPrivacy')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
// 如果有 token,尝试获取用户信息
|
// 如果有 token,尝试获取用户信息
|
||||||
if (userStore.isLogin) {
|
if (userStore.isLogin) {
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ export interface WxLoginResult {
|
|||||||
accessToken: string
|
accessToken: string
|
||||||
refreshToken: string
|
refreshToken: string
|
||||||
userId: number
|
userId: number
|
||||||
|
openId: string
|
||||||
|
mobile: string
|
||||||
|
expiresTime: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 账号密码登录参数(降级方案) */
|
/** 账号密码登录参数(降级方案) */
|
||||||
|
|||||||
+3
-3
@@ -1,9 +1,9 @@
|
|||||||
import { get, post } from './request'
|
import { get, post } from './request'
|
||||||
import type { UserInfo, WxLoginResult, LoginParams } from './types'
|
import type { UserInfo, WxLoginResult, LoginParams } from './types'
|
||||||
|
|
||||||
/** 微信授权登录 */
|
/** 微信小程序登录(loginCode + phoneCode) */
|
||||||
export function wxLogin(code: string): Promise<WxLoginResult> {
|
export function wxLogin(data: { loginCode: string; phoneCode: string }): Promise<WxLoginResult> {
|
||||||
return post<WxLoginResult>('/auth/wx-login', { code }, false)
|
return post<WxLoginResult>('/auth/wx-login', data, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 账号密码登录(降级方案) */
|
/** 账号密码登录(降级方案) */
|
||||||
|
|||||||
+3
-3
@@ -3,11 +3,11 @@
|
|||||||
* 根据 Vite 环境变量读取 API 基础地址等配置
|
* 根据 Vite 环境变量读取 API 基础地址等配置
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** API 基础地址(含 /manage-api 前缀) */
|
/** API 基础地址(含 /mp-api 前缀) */
|
||||||
export const BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:80'
|
export const BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:80'
|
||||||
|
|
||||||
/** API 接口前缀 */
|
/** API 接口前缀(小程序走 MP_API 渠道) */
|
||||||
export const API_PREFIX = '/manage-api'
|
export const API_PREFIX = '/mp-api'
|
||||||
|
|
||||||
/** 完整 API 基础路径 */
|
/** 完整 API 基础路径 */
|
||||||
export const API_BASE = `${BASE_URL}${API_PREFIX}`
|
export const API_BASE = `${BASE_URL}${API_PREFIX}`
|
||||||
|
|||||||
@@ -8,7 +8,10 @@
|
|||||||
|
|
||||||
<view class="login-area">
|
<view class="login-area">
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
<!-- #ifdef MP-WEIXIN -->
|
||||||
<button class="btn-wx-login" @click="handleWxLogin" :disabled="loading">
|
<button class="btn-wx-login"
|
||||||
|
open-type="getPhoneNumber"
|
||||||
|
@getphonenumber="handleGetPhoneNumber"
|
||||||
|
:disabled="loading">
|
||||||
{{ loading ? '登录中...' : '微信一键登录' }}
|
{{ loading ? '登录中...' : '微信一键登录' }}
|
||||||
</button>
|
</button>
|
||||||
<!-- #endif -->
|
<!-- #endif -->
|
||||||
@@ -59,17 +62,43 @@ const form = reactive({
|
|||||||
password: ''
|
password: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
/** 微信一键登录 */
|
/** 微信手机号授权回调 → 登录 */
|
||||||
async function handleWxLogin() {
|
async function handleGetPhoneNumber(e: any) {
|
||||||
|
// 用户拒绝授权手机号
|
||||||
|
if (e.detail.errMsg !== 'getPhoneNumber:ok') {
|
||||||
|
showToast('需要手机号授权才能登录')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
await userStore.wxLogin()
|
const phoneCode = e.detail.code
|
||||||
|
if (!phoneCode) {
|
||||||
|
showToast('手机号获取失败,请重试')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取微信登录 code(与 phoneCode 是完全不同的凭证)
|
||||||
|
const loginRes: any = await new Promise((resolve, reject) => {
|
||||||
|
uni.login({ provider: 'weixin', success: resolve, fail: reject })
|
||||||
|
})
|
||||||
|
|
||||||
|
// 防御性检查:loginCode 不能为空
|
||||||
|
if (!loginRes || !loginRes.code) {
|
||||||
|
showToast('微信登录失败,请重试')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
await userStore.wxLogin({
|
||||||
|
loginCode: loginRes.code, // wx.login() 返回的 code
|
||||||
|
phoneCode: phoneCode // getPhoneNumber 返回的 code
|
||||||
|
})
|
||||||
|
|
||||||
showToast('登录成功', 'success')
|
showToast('登录成功', 'success')
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
uni.switchTab({ url: '/packages/user/pages/index/index' })
|
uni.switchTab({ url: '/pages/index/index' })
|
||||||
}, 1000)
|
}, 1000)
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.error('微信登录失败:', err)
|
|
||||||
showToast(err.message || '登录失败')
|
showToast(err.message || '登录失败')
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
@@ -87,7 +116,7 @@ async function handleFallbackLogin() {
|
|||||||
await userStore.login({ username: form.username, password: form.password })
|
await userStore.login({ username: form.username, password: form.password })
|
||||||
showToast('登录成功', 'success')
|
showToast('登录成功', 'success')
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
uni.switchTab({ url: '/packages/user/pages/index/index' })
|
uni.switchTab({ url: '/pages/index/index' })
|
||||||
}, 1000)
|
}, 1000)
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.error('登录失败:', err)
|
console.error('登录失败:', err)
|
||||||
|
|||||||
+3
-16
@@ -12,27 +12,14 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
|
|
||||||
const isLogin = computed(() => !!token.value)
|
const isLogin = computed(() => !!token.value)
|
||||||
|
|
||||||
/** 微信授权登录 */
|
/** 微信授权登录(接收 loginCode + phoneCode) */
|
||||||
async function wxLogin() {
|
async function wxLogin(params: { loginCode: string; phoneCode: string }) {
|
||||||
// #ifdef MP-WEIXIN
|
const result = await apiWxLogin(params)
|
||||||
const loginRes = await new Promise<UniApp.LoginRes>((resolve, reject) => {
|
|
||||||
uni.login({
|
|
||||||
provider: 'weixin',
|
|
||||||
success: resolve,
|
|
||||||
fail: reject
|
|
||||||
})
|
|
||||||
})
|
|
||||||
const result = await apiWxLogin(loginRes.code)
|
|
||||||
token.value = result.accessToken
|
token.value = result.accessToken
|
||||||
refreshToken.value = result.refreshToken
|
refreshToken.value = result.refreshToken
|
||||||
setToken(result.accessToken)
|
setToken(result.accessToken)
|
||||||
uni.setStorageSync(REFRESH_TOKEN_KEY, result.refreshToken)
|
uni.setStorageSync(REFRESH_TOKEN_KEY, result.refreshToken)
|
||||||
return result
|
return result
|
||||||
// #endif
|
|
||||||
|
|
||||||
// #ifdef H5
|
|
||||||
throw new Error('H5 登录暂未开放,请在微信小程序中使用')
|
|
||||||
// #endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 账号密码登录(降级方案) */
|
/** 账号密码登录(降级方案) */
|
||||||
|
|||||||
Reference in New Issue
Block a user