Files
geekai/web/src/views/Invitation.vue
2025-08-06 09:57:14 +08:00

267 lines
6.8 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>
<div class="custom-scroll">
<div class="page-invitation">
<div class="inner">
<h2 class="text-2xl p-4 font-bold">会员推广计划</h2>
<div class="share-box">
<div class="info">
我们非常欢迎您把此应用分享给您身边的朋友分享成功注册后您和被邀请人都将获得
<strong>{{ invitePower }}</strong>
算力额度作为奖励
你可以保存下面的二维码或者直接复制分享您的专属推广链接发送给微信好友
</div>
<div class="invite-qrcode">
<el-image :src="qrImg" />
</div>
<div class="invite-url">
<span>{{ inviteURL }}</span>
<el-button type="primary" plain class="copy-link" :data-clipboard-text="inviteURL"
>复制链接</el-button
>
</div>
</div>
<div class="invite-stats">
<el-row :gutter="20">
<el-col :span="8">
<div class="item-box yellow">
<el-row :gutter="10">
<el-col :span="10">
<div class="item-icon">
<i class="iconfont icon-role"></i>
</div>
</el-col>
<el-col :span="14">
<div class="item-info">
<div class="num">{{ hits }}</div>
<div class="text">点击量</div>
</div>
</el-col>
</el-row>
</div>
</el-col>
<el-col :span="8">
<div class="item-box blue">
<el-row :gutter="10">
<el-col :span="10">
<div class="item-icon">
<i class="iconfont icon-order"></i>
</div>
</el-col>
<el-col :span="14">
<div class="item-info">
<div class="num">{{ regNum }}</div>
<div class="text">注册量</div>
</div>
</el-col>
</el-row>
</div>
</el-col>
<el-col :span="8">
<div class="item-box bg-green-500">
<el-row :gutter="10">
<el-col :span="10">
<div class="item-icon">
<i class="iconfont icon-chart"></i>
</div>
</el-col>
<el-col :span="14">
<div class="item-info">
<div class="num">{{ rate }}%</div>
<div class="text">转化率</div>
</div>
</el-col>
</el-row>
</div>
</el-col>
</el-row>
</div>
<div class="box-card">
<h2 class="text-xl pb-4">您推荐的用户</h2>
<div class="invite-logs">
<invite-list v-if="isLogin" />
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import InviteList from '@/components/InviteList.vue'
import { checkSession, getSystemInfo } from '@/store/cache'
import { useSharedStore } from '@/store/sharedata'
import { httpGet } from '@/utils/http'
import Clipboard from 'clipboard'
import { ElMessage } from 'element-plus'
import QRCode from 'qrcode'
import { onMounted, ref } from 'vue'
const inviteURL = ref('')
const qrImg = ref('/images/wx.png')
const invitePower = ref(0)
const hits = ref(0)
const regNum = ref(0)
const rate = ref(0)
const isLogin = ref(false)
const store = useSharedStore()
onMounted(() => {
initData()
// 复制链接
const clipboard = new Clipboard('.copy-link')
clipboard.on('success', () => {
ElMessage.success('复制成功!')
})
clipboard.on('error', () => {
ElMessage.error('复制失败!')
})
})
const initData = () => {
checkSession()
.then(() => {
isLogin.value = true
httpGet('/api/invite/code')
.then((res) => {
const text = `${location.protocol}//${location.host}/register?invite_code=${res.data.code}`
hits.value = res.data['hits']
regNum.value = res.data['reg_num']
if (hits.value > 0) {
rate.value = ((regNum.value / hits.value) * 100).toFixed(2)
}
QRCode.toDataURL(text, { width: 400, height: 400, margin: 2 }, (error, url) => {
if (error) {
console.error(error)
} else {
qrImg.value = url
}
})
inviteURL.value = text
})
.catch((e) => {
ElMessage.error('获取邀请码失败:' + e.message)
})
getSystemInfo()
.then((res) => {
invitePower.value = res.data['invite_power']
})
.catch((e) => {
ElMessage.error('获取系统配置失败:' + e.message)
})
})
.catch(() => {
store.setShowLoginDialog(true)
})
}
</script>
<style lang="scss" scoped>
@use '../assets/css/custom-scroll.scss' as *;
.page-invitation {
display: flex;
justify-content: center;
// background-color: #282c34;
height: 100%;
overflow-x: hidden;
overflow-y: visible;
.inner {
display: flex;
flex-flow: column;
max-width: 1000px;
width: 100%;
color: var(--text-theme-color);
h2 {
color: var(--theme-textcolor-normal);
text-align: center;
}
.share-box {
.info {
line-height: 1.5;
// border 1px solid #444444
background: var(--chat-bg);
border-radius: 10px;
padding: 10px;
strong {
color: #f56c6c;
}
}
.invite-qrcode {
padding: 20px;
text-align: center;
}
.invite-url {
padding: 15px;
display: flex;
justify-content: space-between;
border: 1px solid #444444;
border-radius: 10px;
span {
position: relative;
font-family: 'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
top: 5px;
}
}
}
.invite-stats {
padding: 30px 10px;
.item-box {
border-radius: 10px;
padding: 0 10px;
.el-col {
height: 140px;
display: flex;
align-items: center;
justify-content: center;
.iconfont {
font-size: 60px;
}
.item-info {
font-size: 18px;
.text,
.num {
padding: 3px 0;
text-align: center;
}
.num {
font-size: 40px;
}
}
}
}
.yellow {
background-color: #ffeecc;
color: #d68f00;
}
.blue {
background-color: #d6e4ff;
color: #1062fe;
}
}
}
}
</style>