feat: add invitation and promotion functions

This commit is contained in:
RockYang
2023-11-23 16:30:15 +08:00
parent d35164506a
commit a4a1eec30b
17 changed files with 627 additions and 70 deletions

View File

@@ -1,40 +1,118 @@
<template>
<div class="page-invitation" :style="{ height: winHeight + 'px' }">
<div class="page-invitation">
<div class="inner">
<h1>会员推广计划</h1>
<h2>页面正在紧锣密鼓开发中敬请期待</h2>
<h2>会员推广计划</h2>
<div class="share-box">
<div class="info">
我们非常欢迎您把此应用分享给您身边的朋友分享成功注册后您将获得 {{ inviteChatCalls }} 次对话额度以及
{{ inviteImgCalls }} 次AI绘画额度作为奖励
你可以保存下面的二维码或者直接复制分享您的专属推广链接发送给微信好友
</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>
<h2>您推荐用户</h2>
<div class="invite-logs">
<el-empty :image-size="100"/>
</div>
</div>
</div>
</template>
<script setup>
import {ref} from "vue"
import {onMounted, ref} from "vue"
import QRCode from "qrcode";
import {httpGet} from "@/utils/http";
import {ElMessage} from "element-plus";
import Clipboard from "clipboard";
const winHeight = ref(window.innerHeight)
const inviteURL = ref("")
const qrImg = ref("")
const inviteChatCalls = ref(0)
const inviteImgCalls = ref(0)
const users = ref([])
onMounted(() => {
httpGet("/api/invite/code").then(res => {
const text = `${location.protocol}//${location.host}/register?invite_code=${res.data.code}`
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)
})
// 复制链接
const clipboard = new Clipboard('.copy-link');
clipboard.on('success', () => {
ElMessage.success('复制成功!');
})
clipboard.on('error', () => {
ElMessage.error('复制失败!');
})
})
</script>
<style lang="stylus" scoped>
.page-invitation {
display: flex;
justify-content: center;
align-items center
background-color: #282c34;
height 100vh
.inner {
text-align center
h1 {
color: #202020;
font-size: 80px;
font-weight: bold;
letter-spacing: 0.1em;
text-shadow: -1px -1px 1px #111111, 2px 2px 1px #363636;
}
max-width 800px
width 100%
color #e1e1e1
h2 {
color #ffffff;
font-weight: bold;
}
.share-box {
.info {
line-height 1.5
border 1px solid #444444
border-radius 10px
padding 10px
}
.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
}
}
}
}
}

View File

@@ -69,6 +69,19 @@
</el-row>
</div>
<div class="block">
<el-input placeholder="邀请码"
size="large"
v-model="formData.invite_code"
autocomplete="off">
<template #prefix>
<el-icon>
<Message/>
</el-icon>
</template>
</el-input>
</div>
<el-row class="btn-row">
<el-button class="login-btn" size="large" type="primary" @click="register">注册</el-button>
</el-row>
@@ -103,7 +116,7 @@
<script setup>
import {ref} from "vue";
import {Checked, Iphone, Lock} from "@element-plus/icons-vue";
import {Checked, Iphone, Lock, Message} from "@element-plus/icons-vue";
import {httpGet, httpPost} from "@/utils/http";
import {ElMessage} from "element-plus";
import {useRouter} from "vue-router";
@@ -121,6 +134,7 @@ const formData = ref({
password: '',
code: '',
repass: '',
invite_code: router.currentRoute.value.query['invite_code'],
})
const formRef = ref(null)
const enableMsg = ref(false)
@@ -134,6 +148,11 @@ httpGet('/api/sms/status').then(res => {
}
})
httpGet("/api/invite/hits", {code: formData.value.invite_code}).then(() => {
}).catch(() => {
})
const register = function () {
if (!validateMobile(formData.value.mobile)) {
return ElMessage.error('请输入合法的手机号');

View File

@@ -10,14 +10,20 @@
<el-input v-model="system['admin_title']"/>
</el-form-item>
<el-form-item label="注册赠送对话次数" prop="user_init_calls">
<el-input v-model.number="system['user_init_calls']" placeholder="新用户注册赠送对话次数"/>
</el-form-item>
<el-form-item label="VIP每月对话次数" prop="vip_month_calls">
<el-input v-model.number="system['vip_month_calls']" placeholder="VIP用户每月赠送对话次数"/>
<el-input v-model.number="system['init_chat_calls']" placeholder="新用户注册赠送对话次数"/>
</el-form-item>
<el-form-item label="注册赠送绘图次数" prop="init_img_calls">
<el-input v-model.number="system['init_img_calls']" placeholder="新用户注册赠送绘图次数"/>
</el-form-item>
<el-form-item label="邀请赠送对话次数" prop="invite_chat_calls">
<el-input v-model.number="system['invite_chat_calls']" placeholder="邀请新用户注册赠送对话次数"/>
</el-form-item>
<el-form-item label="邀请赠送绘图次数" prop="invite_img_calls">
<el-input v-model.number="system['invite_img_calls']" placeholder="邀请新用户注册赠送绘图次数"/>
</el-form-item>
<el-form-item label="VIP每月对话次数" prop="vip_month_calls">
<el-input v-model.number="system['vip_month_calls']" placeholder="VIP用户每月赠送对话次数"/>
</el-form-item>
<el-form-item label="开放注册服务" prop="enabled_register">
<el-switch v-model="system['enabled_register']"/>
</el-form-item>
@@ -319,7 +325,7 @@ onMounted(() => {
const rules = reactive({
title: [{required: true, message: '请输入网站标题', trigger: 'blur',}],
admin_title: [{required: true, message: '请输入控制台标题', trigger: 'blur',}],
user_init_calls: [{required: true, message: '请输入赠送对话次数', trigger: 'blur'}],
init_chat_calls: [{required: true, message: '请输入赠送对话次数', trigger: 'blur'}],
user_img_calls: [{required: true, message: '请输入赠送绘图次数', trigger: 'blur'}],
})
const save = function (key) {