完成一键登录和支付功能
This commit is contained in:
@@ -0,0 +1,249 @@
|
||||
/**
|
||||
* 登录拦截Hook
|
||||
* 用于在需要登录的操作前检查用户登录状态,未登录则弹出登录框
|
||||
*
|
||||
* 使用方式:
|
||||
* import { useLoginGuard } from '@/common/hooks/useLoginGuard.js'
|
||||
*
|
||||
* const { checkLogin, requireLogin } = useLoginGuard()
|
||||
*
|
||||
* // 方式1:检查登录状态(返回布尔值)
|
||||
* if (!checkLogin()) return
|
||||
*
|
||||
* // 方式2:需要登录才执行(推荐)
|
||||
* await requireLogin()
|
||||
* // 之后的代码只有在登录后才执行
|
||||
*
|
||||
* // 方式3:在点击事件中使用
|
||||
* async function handleClick() {
|
||||
* await requireLogin()
|
||||
* // 执行需要登录的操作
|
||||
* }
|
||||
*/
|
||||
|
||||
import { getToken } from '@/utils/request.js'
|
||||
import { loadMemberStore } from '@/common/memberInfo/store.js'
|
||||
|
||||
// 保存当前页面的登录弹窗引用
|
||||
let loginModalRef = null
|
||||
|
||||
/**
|
||||
* 注册登录弹窗组件
|
||||
* 在App.vue或页面onMounted中调用
|
||||
* @param {Object} modalRef - loginModal组件的ref
|
||||
*/
|
||||
export function registerLoginModal(modalRef) {
|
||||
loginModalRef = modalRef
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前登录状态
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function isLoggedIn() {
|
||||
const token = getToken()
|
||||
const isLoginStorage = uni.getStorageSync('isLogin')
|
||||
return !!(token || isLoginStorage)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取登录用户信息
|
||||
* @returns {Object|null}
|
||||
*/
|
||||
export function getLoginUser() {
|
||||
const store = loadMemberStore()
|
||||
return store.profile || null
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用登录拦截Hook
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function useLoginGuard() {
|
||||
|
||||
/**
|
||||
* 检查登录状态(同步)
|
||||
* @returns {Boolean} 是否已登录
|
||||
*/
|
||||
function checkLogin() {
|
||||
return isLoggedIn()
|
||||
}
|
||||
|
||||
/**
|
||||
* 需要登录才继续执行(异步)
|
||||
* 如果未登录,弹出登录框,等待用户登录或取消
|
||||
* @param {Object} options - 配置选项
|
||||
* @param {String} options.title - 弹窗标题
|
||||
* @param {String} options.subtitle - 弹窗副标题
|
||||
* @param {Function} options.onSuccess - 登录成功回调
|
||||
* @param {Function} options.onCancel - 取消登录回调
|
||||
* @returns {Promise<Boolean>} 是否已登录(用户登录成功返回true,取消返回false)
|
||||
*/
|
||||
async function requireLogin(options = {}) {
|
||||
// 如果已经登录,直接返回true
|
||||
if (isLoggedIn()) {
|
||||
return true
|
||||
}
|
||||
|
||||
// 如果传入了onSuccess回调,先检查
|
||||
if (options.onSuccess) {
|
||||
const store = loadMemberStore()
|
||||
if (store.profile?.id) {
|
||||
options.onSuccess(store.profile)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// 显示登录弹窗
|
||||
return new Promise((resolve) => {
|
||||
if (!loginModalRef) {
|
||||
console.warn('[useLoginGuard] 登录弹窗未注册,请先调用 registerLoginModal')
|
||||
// 尝试跳转到登录页
|
||||
uni.navigateTo({
|
||||
url: '/pages/memberInfo/login',
|
||||
fail: () => {
|
||||
uni.showToast({
|
||||
title: '请先登录',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
})
|
||||
resolve(false)
|
||||
return
|
||||
}
|
||||
|
||||
// 保存resolve函数
|
||||
let resolvePromise = resolve
|
||||
|
||||
// 显示登录弹窗
|
||||
loginModalRef.show()
|
||||
|
||||
// 监听登录成功
|
||||
const loginSuccessHandler = (result) => {
|
||||
if (options.onSuccess) {
|
||||
options.onSuccess(result)
|
||||
}
|
||||
resolvePromise(true)
|
||||
}
|
||||
|
||||
// 监听登录失败/取消
|
||||
const closeHandler = () => {
|
||||
if (options.onCancel) {
|
||||
options.onCancel()
|
||||
}
|
||||
resolvePromise(false)
|
||||
}
|
||||
|
||||
// 注册事件监听
|
||||
uni.$once('loginModal:success', loginSuccessHandler)
|
||||
uni.$once('loginModal:close', closeHandler)
|
||||
|
||||
// 设置超时
|
||||
setTimeout(() => {
|
||||
uni.$off('loginModal:success', loginSuccessHandler)
|
||||
uni.$off('loginModal:close', closeHandler)
|
||||
}, 60000) // 60秒超时
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全执行函数(仅登录后执行)
|
||||
* @param {Function} fn - 要执行的函数
|
||||
* @param {Object} options - 配置选项
|
||||
* @returns {Promise<any>} 函数返回值或null
|
||||
*/
|
||||
async function safeExecute(fn, options = {}) {
|
||||
const loggedIn = await requireLogin(options)
|
||||
if (loggedIn && typeof fn === 'function') {
|
||||
return await fn()
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* 包装需要登录的API调用
|
||||
* @param {Function} apiFn - API函数
|
||||
* @param {Array} args - API参数
|
||||
* @param {Object} options - 配置选项
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
async function callLoggedInApi(apiFn, args = [], options = {}) {
|
||||
const loggedIn = await requireLogin(options)
|
||||
if (loggedIn && typeof apiFn === 'function') {
|
||||
return await apiFn(...args)
|
||||
}
|
||||
throw new Error('用户未登录')
|
||||
}
|
||||
|
||||
return {
|
||||
checkLogin,
|
||||
requireLogin,
|
||||
safeExecute,
|
||||
callLoggedInApi,
|
||||
isLoggedIn,
|
||||
getLoginUser
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建登录拦截Mixin(用于选项式API)
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function loginGuardMixin() {
|
||||
return {
|
||||
data() {
|
||||
return {
|
||||
isLogin: false
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
this.checkLoginStatus()
|
||||
},
|
||||
onShow() {
|
||||
this.checkLoginStatus()
|
||||
},
|
||||
methods: {
|
||||
checkLoginStatus() {
|
||||
this.isLogin = isLoggedIn()
|
||||
},
|
||||
|
||||
async ensureLogin() {
|
||||
if (!this.isLogin) {
|
||||
if (!loginModalRef) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/memberInfo/login'
|
||||
})
|
||||
return false
|
||||
}
|
||||
loginModalRef.show()
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 路由守卫配置
|
||||
* 配置需要登录的页面路径
|
||||
*/
|
||||
export const protectedRoutes = [
|
||||
'/pages/memberInfo/memberInfo',
|
||||
'/pages/memberInfo/purchaseCard',
|
||||
'/pages/memberInfo/memberCard',
|
||||
'/pages/memberInfo/checkIn',
|
||||
'/pages/memberInfo/booking',
|
||||
'/pages/memberInfo/coupons',
|
||||
'/pages/memberInfo/points',
|
||||
'/pages/memberInfo/userInfo'
|
||||
]
|
||||
|
||||
/**
|
||||
* 检查当前页面是否需要登录
|
||||
* @param {String} currentPage - 当前页面路径
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function isProtectedRoute(currentPage) {
|
||||
return protectedRoutes.some(route => currentPage.includes(route))
|
||||
}
|
||||
Reference in New Issue
Block a user