5.3 KiB
5.3 KiB
/**
- 登录弹窗组件使用示例
- 该组件提供了统一的登录拦截功能,可以在任何页面使用 */
方式一:在页面中直接使用LoginModal组件
<template>
<view>
<!-- 其他内容 -->
<!-- 引入登录弹窗 -->
<LoginModal
ref="loginModalRef"
v-model="showLoginModal"
title="登录后享受更多服务"
subtitle="登录即表示同意相关协议"
:show-close="true"
:mask-closable="true"
@loginSuccess="onLoginSuccess"
@loginError="onLoginError"
/>
</view>
</template>
<script setup>
import { ref, nextTick } from 'vue'
import { registerLoginModal } from '@/common/hooks/useLoginGuard.js'
import LoginModal from '@/components/global/LoginModal.vue'
const showLoginModal = ref(false)
const loginModalRef = ref(null)
// 注册到全局
onMounted(() => {
nextTick(() => {
if (loginModalRef.value) {
registerLoginModal(loginModalRef.value)
}
})
})
// 显示登录弹窗
function showLogin() {
showLoginModal.value = true
}
// 登录成功回调
function onLoginSuccess(result) {
console.log('登录成功', result)
// 刷新页面数据等
}
// 登录失败回调
function onLoginError(error) {
console.log('登录失败', error)
}
</script>
方式二:使用 useLoginGuard Hook
<script setup>
import { useLoginGuard } from '@/common/hooks/useLoginGuard.js'
const { requireLogin, checkLogin } = useLoginGuard()
// 示例1:需要登录才能执行的操作
async function handleBookCourse() {
// 检查是否已登录
if (!checkLogin()) {
return
}
// 执行预约操作...
}
// 示例2:弹窗式登录(推荐)
async function handlePurchase() {
const loggedIn = await requireLogin({
title: '请先登录',
subtitle: '登录后即可购买会员卡',
onSuccess: (user) => {
console.log('登录成功,用户信息:', user)
}
})
if (loggedIn) {
// 执行购买操作
await purchaseCard()
}
}
// 示例3:安全执行函数
async function handleCheckIn() {
const result = await requireLogin().safeExecute(async () => {
// 只有登录后才能执行这里的代码
return await checkInApi()
})
if (result) {
uni.showToast({ title: '签到成功' })
}
}
// 示例4:包装API调用
async function handleGetCoupons() {
const { callLoggedInApi } = useLoginGuard()
try {
const coupons = await callLoggedInApi(getCouponsApi, [], {
title: '领取优惠券'
})
console.log('优惠券列表:', coupons)
} catch (e) {
if (e.message === '用户未登录') {
// 用户未登录,弹窗已显示
}
}
}
</script>
方式三:在组件中使用登录守卫Mixin
<script>
import { loginGuardMixin } from '@/common/hooks/useLoginGuard.js'
export default {
mixins: [loginGuardMixin()],
methods: {
async onQuickAction(type) {
// 自动检查登录状态
if (!await this.ensureLogin()) {
return
}
// 已登录,执行操作
if (type === 'book') {
this.goToBooking()
}
}
}
}
</script>
登录弹窗组件Props说明
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| modelValue | Boolean | false | 控制显示/隐藏 |
| title | String | '登录后享受更多服务' | 弹窗标题 |
| subtitle | String | '登录即表示同意相关协议' | 弹窗副标题 |
| showClose | Boolean | true | 是否显示关闭按钮 |
| modalStyle | String | 'center' | 弹窗样式:'center'居中,'bottom'底部 |
| maskClosable | Boolean | true | 点击遮罩是否关闭 |
| onLoginSuccess | Function | null | 登录成功回调 |
| onLoginError | Function | null | 登录失败回调 |
登录弹窗组件Events
| 事件名 | 说明 | 回调参数 |
|---|---|---|
| update:modelValue | 显示状态变化 | Boolean |
| loginSuccess | 登录成功 | Object: 登录结果 |
| loginError | 登录失败 | Error: 错误对象 |
| close | 弹窗关闭 | - |
登录弹窗组件暴露的方法
| 方法名 | 说明 | 参数 |
|---|---|---|
| show() | 显示弹窗 | - |
| hide() | 隐藏弹窗 | - |
| switchCard(card) | 切换登录方式 | 'phone'一键登录 / 'sms'验证码登录 |
全局登录拦截示例
在 App.vue 中注册全局登录弹窗:
<script>
import LoginModal from '@/components/global/LoginModal.vue'
import { registerLoginModal } from '@/common/hooks/useLoginGuard.js'
export default {
components: { LoginModal },
onLaunch() {
// 注册全局登录弹窗
this.$nextTick(() => {
if (this.$refs.globalLoginModal) {
registerLoginModal(this.$refs.globalLoginModal)
}
})
}
}
</script>
<template>
<view id="app">
<router-view />
<LoginModal ref="globalLoginModal" />
</view>
</template>
API路径配置
登录弹窗组件使用的API路径定义在 @/api/main.js:
// 一键登录
export function phoneLogin(data) {
return request.post('/auth/phone/login', data)
}
// 短信验证码登录
export function smsLogin(data) {
return request.post('/auth/phone/sms/login', data)
}
// 发送验证码
export function sendSmsCode(phone) {
return request.post('/auth/phone/sms/send', { phone })
}
如需修改API路径,请编辑 main.js 文件中的相应函数。