Files
offerpai_web/src/components/SettingsInviteDialog.vue
T
2026-07-08 18:58:27 +08:00

125 lines
4.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<!-- 邀请注册送会员弹窗 -->
<Teleport to="body">
<div v-if="modelValue" class="settings-invite-overlay" @click="$emit('update:modelValue', false)">
<div class="settings-invite-dialog" @click.stop>
<!-- 顶部标题 + 关闭按钮 -->
<div class="settings-invite-dialog__header">
<div class="settings-invite-dialog__header-text">
<h2 class="settings-invite-dialog__title">邀请好友免费获取 7 天会员</h2>
<p class="settings-invite-dialog__subtitle">好友通过你的链接注册并完成认证 3 天会员</p>
</div>
<!-- 关闭按钮 -->
<span class="settings-invite-dialog__close" @click="$emit('update:modelValue', false)"></span>
</div>
<!-- 邀请链接区域 -->
<div class="settings-invite-dialog__link-box">
<span class="settings-invite-dialog__link-text">{{ inviteUrl }}</span>
<span class="settings-invite-dialog__copy-btn" @click="handleCopy">复制</span>
</div>
<!-- 邀请步骤区域 -->
<div class="settings-invite-dialog__steps">
<span class="settings-invite-dialog__steps-title">邀请步骤</span>
<div class="settings-invite-dialog__steps-list">
<!-- 步骤1 -->
<div class="settings-invite-dialog__step-item">
<span class="settings-invite-dialog__step-num">1</span>
<span class="settings-invite-dialog__step-text">分享专属邀请链接给好友</span>
</div>
<!-- 步骤2 -->
<div class="settings-invite-dialog__step-item">
<span class="settings-invite-dialog__step-num">2</span>
<span class="settings-invite-dialog__step-text">好友完成注册并通过认证</span>
</div>
<!-- 步骤3 -->
<div class="settings-invite-dialog__step-item">
<span class="settings-invite-dialog__step-num">3</span>
<span class="settings-invite-dialog__step-text">获得 7 天会员奖励</span>
</div>
</div>
</div>
<!-- 底部统计 + 按钮 -->
<div class="settings-invite-dialog__footer">
<div class="settings-invite-dialog__stat">
<span class="settings-invite-dialog__stat-line">已邀请<em>{{ totalFriends }}</em></span>
<span class="settings-invite-dialog__stat-line">累计获得<em>{{ totalDays }}</em></span>
</div>
<button class="settings-invite-dialog__member-btn" @click="handleGoMember">
<span>成为正式会员</span>
<span class="settings-invite-dialog__member-btn-arrow"></span>
</button>
</div>
</div>
</div>
</Teleport>
<!-- 会员购买弹窗 -->
<MemberDialog v-model="showMemberDialog" />
</template>
<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { useStore } from 'vuex'
import { ElMessage } from 'element-plus'
import MemberDialog from './MemberDialog.vue'
import { fetchInviteStats } from '@/api/member'
/** 组件 Props */
const props = defineProps<{ modelValue: boolean }>()
/** 组件 Emits */
defineEmits<{
(e: 'update:modelValue', value: boolean): void
}>()
const store = useStore()
/** 会员弹窗显示状态 */
const showMemberDialog = ref(false)
/** 累计获得会员天数 */
const totalDays = ref(0)
/** 累计邀请好友数 */
const totalFriends = ref(0)
/**
* 弹窗打开时请求邀请统计接口
*/
watch(() => props.modelValue, async (val) => {
if (val) {
try {
const res = await fetchInviteStats()
totalFriends.value = res.data?.inviteCount ?? 0
totalDays.value = res.data?.rewardDays ?? 0
} catch (e) {
console.error('获取邀请统计失败', e)
}
}
})
/** 用户邀请码 — 从全局 store 读取 */
const inviteCode = computed(() => store.state.userInfo?.inviteCode || 'NOVA2026')
/** 邀请链接地址 */
const inviteUrl = computed(() => `https://www.offerpai.com.cn/invite?code=${inviteCode.value}`)
/** 复制链接到剪贴板 */
async function handleCopy() {
try {
await navigator.clipboard.writeText(inviteUrl.value)
ElMessage.success('链接已复制')
} catch {
ElMessage.error('复制失败,请手动复制')
}
}
/** 打开会员购买弹窗 */
function handleGoMember() {
showMemberDialog.value = true
}
</script>