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