|
|
@@ -0,0 +1,233 @@
|
|
|
+<template>
|
|
|
+ <PageContainer nav-title="分享赚钱">
|
|
|
+ <view class="share-earn-page">
|
|
|
+ <scroll-view scroll-y class="page-scroll">
|
|
|
+ <view class="page-content">
|
|
|
+ <view class="invite-card">
|
|
|
+ <view class="invite-heading">
|
|
|
+ <text>邀请好友</text>
|
|
|
+ <button class="invite-code" @click="copyCode">
|
|
|
+ <text class="muted">我的邀请码</text>
|
|
|
+ <text class="code-value">{{ invitationCode || '--' }}</text>
|
|
|
+ <u-icon name="file-text" color="#d9b34b" size="24" />
|
|
|
+ </button>
|
|
|
+ </view>
|
|
|
+ <view class="invite-body">
|
|
|
+ <button class="qr-card" @click="saveQrCode">
|
|
|
+ <image v-if="qrImage" :src="qrImage" class="qr-image" mode="aspectFit" />
|
|
|
+ <view v-else class="qr-placeholder">登录后生成<br />邀请二维码</view>
|
|
|
+ <text class="save-label">保存邀请码</text>
|
|
|
+ </button>
|
|
|
+ <view class="share-tools">
|
|
|
+ <button class="link-field" @click="copyLink">
|
|
|
+ <text class="link-text">{{ invitationLink || '登录后获取专属邀请链接' }}</text>
|
|
|
+ <view class="link-copy"><u-icon name="file-text" color="#d9b34b" size="28" /></view>
|
|
|
+ </button>
|
|
|
+ <view class="share-channels">
|
|
|
+ <button v-for="channel in channels" :key="channel.name" class="share-channel"
|
|
|
+ @click="shareTo(channel.name)">
|
|
|
+ <view v-if="channel.name === '分享'" class="share-icon">
|
|
|
+ <u-icon name="share" color="#d9b34b" size="40" />
|
|
|
+ </view>
|
|
|
+ <image v-else :src="`/static/images/share-earn/${channel.icon}.svg`" class="channel-icon" />
|
|
|
+ <text>{{ channel.name }}</text>
|
|
|
+ </button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <text class="section-title">代理教程</text>
|
|
|
+ <view class="commission-tabs">
|
|
|
+ <button v-for="tab in tabs" :key="tab" class="commission-tab"
|
|
|
+ :class="{ active: selected === tab }" @click="selected = tab">
|
|
|
+ {{ tab }}的佣金
|
|
|
+ </button>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="commission-summary">
|
|
|
+ <view class="agent-portrait summary-portrait">
|
|
|
+ <image :src="selected === 'A' ? '/static/images/share-earn/agent-a.svg' : '/static/images/share-earn/agent.svg'" />
|
|
|
+ <text class="agent-badge">{{ selected }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="summary-lines">
|
|
|
+ <view>直属业绩={{ current.performance }}</view>
|
|
|
+ <view>直属佣金={{ current.total }}*10%=<text class="gold">{{ current.direct }}</text></view>
|
|
|
+ <view>其他佣金=<text class="gold">{{ current.otherFormula }}</text></view>
|
|
|
+ <view>本期佣金={{ current.direct }}+{{ current.other }}=<text class="gold">{{ current.income }}</text></view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <CommissionTree :agent="selected" />
|
|
|
+
|
|
|
+ <view class="rules-card">
|
|
|
+ <view class="rules-title">举例说明如下:</view>
|
|
|
+ <view class="paragraph">假设当前有效投注的返佣比例为10%(即来自直属下级),跨级部分额外佣金为比例中的比例(站长额外赠送),赠送比例为30%。A是第一个发掘商机的,马上发展了B1和B2;B1又往下发展了C1和C2;B2往下发展了C3。第二天B1的有效投注为500,B2的有效投注为3000,C1的有效投注为1000,C2的有效投注为2000,C3的有效投注为20000。</view>
|
|
|
+ <view>那么他们之间的收益计算方式如下:</view>
|
|
|
+ <view class="rules-title">1、{{ selected }}的收益计算方式如下:</view>
|
|
|
+ <view v-if="selected === 'A'">
|
|
|
+ <view class="paragraph"><text class="rule-number">(1)A说明:</text>A的佣金来源除了直属下级B1和B2贡献,还有来自其他下级C1、C2和C3贡献。</view>
|
|
|
+ <view class="paragraph"><text class="rule-number">(2)A的直属业绩:</text>即A的直属下级B1和B2给A贡献的业绩,计算公式为:直属业绩=B1有效投注+B2有效投注=500+3000=3500;</view>
|
|
|
+ <view class="paragraph"><text class="rule-number">(3)A的直属佣金:</text>直属佣金=直属业绩*返佣比例=3500*10%=<text class="gold">350;</text></view>
|
|
|
+ <view class="paragraph"><text class="rule-number">(4)A的其他佣金:</text>即来自C1、C2和C3贡献佣金,计算公式为:其他佣金=(C1有效投注+C2有效投注+C3有效投注)*返佣比例*赠送比例=(1000+2000+20000)*10%*30%=<text class="gold">690;</text></view>
|
|
|
+ <view class="paragraph"><text class="rule-number">(5)A的本期佣金:</text>本期佣金=直属佣金+其他佣金=<text class="gold">350+690=1040。</text></view>
|
|
|
+ </view>
|
|
|
+ <view v-else-if="selected === 'B1'">
|
|
|
+ <view class="paragraph"><text class="rule-number">(1)B1说明:</text>B1的直属下级为C1和C2,他们的有效投注分别为1000和2000。</view>
|
|
|
+ <view class="paragraph"><text class="rule-number">(2)B1的直属业绩:</text>直属业绩=C1有效投注+C2有效投注=1000+2000=3000;</view>
|
|
|
+ <view class="paragraph"><text class="rule-number">(3)B1的直属佣金:</text>直属佣金=3000*10%=<text class="gold">300;</text></view>
|
|
|
+ <view class="paragraph"><text class="rule-number">(4)B1的其他佣金:</text>本例中C1、C2暂无下级,其他佣金=<text class="gold">0;</text></view>
|
|
|
+ <view class="paragraph"><text class="rule-number">(5)B1的本期佣金:</text>本期佣金=直属佣金+其他佣金=<text class="gold">300+0=300。</text></view>
|
|
|
+ </view>
|
|
|
+ <view v-else>
|
|
|
+ <view class="paragraph"><text class="rule-number">(1)B2说明:</text>B2的直属下级为C3,有效投注为20000。</view>
|
|
|
+ <view class="paragraph"><text class="rule-number">(2)B2的直属业绩:</text>直属业绩=C3有效投注=<text class="gold">20000;</text></view>
|
|
|
+ <view class="paragraph"><text class="rule-number">(3)B2的直属佣金:</text>直属佣金=20000*10%=<text class="gold">2000;</text></view>
|
|
|
+ <view class="paragraph"><text class="rule-number">(4)B2的其他佣金:</text>本例中C3暂无下级,其他佣金=<text class="gold">0;</text></view>
|
|
|
+ <view class="paragraph"><text class="rule-number">(5)B2的本期佣金:</text>本期佣金=直属佣金+其他佣金=<text class="gold">2000+0=2000。</text></view>
|
|
|
+ </view>
|
|
|
+ <view class="rules-title">2、全民代理补充说明:</view>
|
|
|
+ <view class="paragraph">因全民代理“代理模式”可以发展无限下级,即N代表无限级,即可横向发展同时也可以纵向发展。为了便于解说,本文只取2层结构作为例子阐述。</view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </scroll-view>
|
|
|
+ </view>
|
|
|
+ </PageContainer>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { computed, ref } from 'vue'
|
|
|
+import { onShow } from '@dcloudio/uni-app'
|
|
|
+import qrcode from 'qrcode-generator'
|
|
|
+import PageContainer from '@/components/PageContainer/index.vue'
|
|
|
+import CommissionTree from './CommissionTree.vue'
|
|
|
+
|
|
|
+const userInfo = ref({})
|
|
|
+const selected = ref('A')
|
|
|
+const tabs = ['A', 'B1', 'B2']
|
|
|
+const channels = [
|
|
|
+ { name: '分享' }, { name: 'Wechat', icon: 'wechat' },
|
|
|
+ { name: '抖音', icon: 'douyin' }, { name: '快手', icon: 'kuaishou' }, { name: 'QQ', icon: 'qq' },
|
|
|
+]
|
|
|
+const examples = {
|
|
|
+ A: { performance: '500+3000=3500', total: 3500, direct: 350, otherFormula: '30+60+600=690', other: 690, income: 1040 },
|
|
|
+ B1: { performance: '1000+2000=3000', total: 3000, direct: 300, otherFormula: '0', other: 0, income: 300 },
|
|
|
+ B2: { performance: '20000', total: 20000, direct: 2000, otherFormula: '0', other: 0, income: 2000 },
|
|
|
+}
|
|
|
+const current = computed(() => examples[selected.value])
|
|
|
+const invitationCode = computed(() => String(userInfo.value.user_code || ''))
|
|
|
+const invitationLink = computed(() => {
|
|
|
+ if (!invitationCode.value) return ''
|
|
|
+ let base = 'https://www.f1bet888.com/'
|
|
|
+ // #ifdef H5
|
|
|
+ base = window.location.href.split('#')[0]
|
|
|
+ // #endif
|
|
|
+ return `${base}#/pages/register/index?invitationCode=${encodeURIComponent(invitationCode.value)}`
|
|
|
+})
|
|
|
+const qrImage = computed(() => {
|
|
|
+ if (!invitationLink.value) return ''
|
|
|
+ const code = qrcode(0, 'M')
|
|
|
+ code.addData(invitationLink.value)
|
|
|
+ code.make()
|
|
|
+ return code.createDataURL(6, 8)
|
|
|
+})
|
|
|
+
|
|
|
+function requireCode() {
|
|
|
+ if (invitationCode.value) return true
|
|
|
+ uni.showToast({ title: '请先登录后获取邀请码', icon: 'none' })
|
|
|
+ return false
|
|
|
+}
|
|
|
+function copyText(data, title = '复制成功') {
|
|
|
+ uni.setClipboardData({ data, showToast: false, success: () => uni.showToast({ title, icon: 'none' }) })
|
|
|
+}
|
|
|
+function copyCode() {
|
|
|
+ if (requireCode()) copyText(invitationCode.value)
|
|
|
+}
|
|
|
+function copyLink() {
|
|
|
+ if (requireCode()) copyText(invitationLink.value, '邀请链接已复制')
|
|
|
+}
|
|
|
+async function shareTo(channel) {
|
|
|
+ if (!requireCode()) return
|
|
|
+ // #ifdef H5
|
|
|
+ if (channel === '分享' && navigator.share) {
|
|
|
+ try {
|
|
|
+ await navigator.share({ title: '邀请好友', text: '使用我的邀请码注册', url: invitationLink.value })
|
|
|
+ } catch (error) {
|
|
|
+ if (error.name !== 'AbortError') copyLink()
|
|
|
+ }
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // #endif
|
|
|
+ const platform = channel === 'Wechat' ? '微信' : channel
|
|
|
+ copyText(invitationLink.value, channel === '分享' ? '邀请链接已复制' : `链接已复制,请前往${platform}粘贴分享`)
|
|
|
+}
|
|
|
+function saveQrCode() {
|
|
|
+ if (!requireCode()) return
|
|
|
+ // #ifdef H5
|
|
|
+ const link = document.createElement('a')
|
|
|
+ link.href = qrImage.value
|
|
|
+ link.download = `邀请码-${invitationCode.value}.gif`
|
|
|
+ document.body.appendChild(link)
|
|
|
+ link.click()
|
|
|
+ link.remove()
|
|
|
+ return
|
|
|
+ // #endif
|
|
|
+ // #ifdef APP-PLUS
|
|
|
+ const bitmap = new plus.nativeObj.Bitmap('invitation-qr')
|
|
|
+ bitmap.loadBase64Data(qrImage.value, () => {
|
|
|
+ bitmap.save(`_doc/invitation-${Date.now()}.png`, { overwrite: true, format: 'png' }, (result) => {
|
|
|
+ uni.saveImageToPhotosAlbum({ filePath: result.target, success: () => uni.showToast({ title: '保存成功' }), complete: () => bitmap.clear() })
|
|
|
+ }, () => { bitmap.clear(); uni.showToast({ title: '保存失败,请重试', icon: 'none' }) })
|
|
|
+ }, () => { bitmap.clear(); uni.showToast({ title: '保存失败,请重试', icon: 'none' }) })
|
|
|
+ // #endif
|
|
|
+}
|
|
|
+onShow(() => {
|
|
|
+ const stored = uni.getStorageSync('user_info')
|
|
|
+ if (typeof stored === 'string') {
|
|
|
+ try { userInfo.value = JSON.parse(stored) || {} } catch { userInfo.value = {} }
|
|
|
+ } else userInfo.value = stored || {}
|
|
|
+})
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+.share-earn-page { min-height: 100%; background: #fff; color: #333; font-size: 13px; }
|
|
|
+button { margin: 0; padding: 0; border: 0; border-radius: 0; background: transparent; color: inherit; font-size: inherit; line-height: inherit; }
|
|
|
+button::after { border: 0; }
|
|
|
+.page-scroll { height: calc(100vh - 94px - env(safe-area-inset-top)); }
|
|
|
+.page-content { max-width: 520px; margin: 0 auto; padding: 10px 10px calc(10px + env(safe-area-inset-bottom)); box-sizing: border-box; }
|
|
|
+.invite-card, .commission-summary, .rules-card { background: #f8f7f3; border: 1px solid #eeeae1; border-radius: 8px; box-shadow: none; }
|
|
|
+.invite-card { padding: 0 11px 16px; margin-bottom: 12px; }
|
|
|
+.invite-heading { display: flex; align-items: center; justify-content: space-between; height: 38px; border-bottom: 1px solid #ededed; font-weight: 600; }
|
|
|
+.invite-code { display: flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 400; }
|
|
|
+.muted { color: #858585; }
|
|
|
+.code-value { font-weight: 600; }
|
|
|
+.invite-body { display: flex; align-items: flex-start; gap: 16px; padding-top: 12px; }
|
|
|
+.qr-card { flex-shrink: 0; width: 66px; border-radius: 5px; background: #d2ad50; overflow: hidden; }
|
|
|
+.qr-image, .qr-placeholder { display: block; width: 66px; height: 66px; background: #fff; }
|
|
|
+.qr-placeholder { display: flex; align-items: center; justify-content: center; color: #777; font-size: 10px; line-height: 17px; }
|
|
|
+.save-label { display: block; line-height: 36px; font-size: 11px; color: #665124; }
|
|
|
+.share-tools { flex: 1; min-width: 0; }
|
|
|
+.link-field { display: flex; align-items: center; width: 100%; height: 38px; padding-left: 10px; border: 1px solid #e3e3e3; border-radius: 7px; color: #777; box-sizing: border-box; }
|
|
|
+.link-text { flex: 1; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: 11px; text-align: left; }
|
|
|
+.link-copy { display: flex; justify-content: center; align-items: center; width: 36px; margin-left: 8px; border-left: 1px solid #e8e8e8; }
|
|
|
+.share-channels { display: flex; justify-content: space-between; margin-top: 10px; gap: 4px; }
|
|
|
+.share-channel { display: flex; flex-direction: column; align-items: center; gap: 3px; font-size: 12px; color: #666; }
|
|
|
+.share-icon, .channel-icon { display: flex; align-items: center; justify-content: center; width: 35px; height: 35px; }
|
|
|
+.share-icon { border: 1px solid #e5e5e5; border-radius: 50%; box-sizing: border-box; }
|
|
|
+.section-title { display: block; font-size: 16px; line-height: 24px; margin-bottom: 8px; color: #242424; }
|
|
|
+.commission-tabs { display: flex; gap: 12px; margin-bottom: 10px; }
|
|
|
+.commission-tab { padding: 4px 11px; border-radius: 20px; border: 1px solid #dedede; background: #f7f7f7; font-size: 12px; color: #666; }
|
|
|
+.commission-tab.active { color: #59451e; border-color: #d7b34c; background: #d7b34c; }
|
|
|
+.commission-summary { display: flex; align-items: center; min-height: 97px; padding: 10px; box-sizing: border-box; background: #eee2af; border-color: #dfcc95; color: #3f3624; }
|
|
|
+.agent-portrait { position: relative; width: 50px; height: 50px; border: 1px solid #e3ba44; border-radius: 50%; background: #f5f5ef; flex-shrink: 0; }
|
|
|
+.agent-portrait image { width: 100%; height: 100%; border-radius: 50%; }
|
|
|
+.agent-badge { position: absolute; bottom: -2px; right: -3px; min-width: 15px; height: 15px; line-height: 15px; padding: 0 1px; text-align: center; border-radius: 50%; background: #ffbd00; color: #fff; font-size: 11px; font-weight: 600; }
|
|
|
+.summary-portrait { margin-right: 48px; }
|
|
|
+.summary-lines { font-size: 12px; line-height: 19px; letter-spacing: -0.3px; }
|
|
|
+.gold { color: #a87500; font-weight: 600; }
|
|
|
+.rules-card { margin-top: 11px; padding: 9px 11px 12px; font-size: 13px; line-height: 21px; color: #454545; }
|
|
|
+.rules-title, .rule-number { color: #252525; }
|
|
|
+.rules-title, .rule-number { font-weight: 600; }
|
|
|
+.paragraph { text-indent: 2em; }
|
|
|
+@media (max-width: 350px) { .summary-portrait { margin-right: 28px; } .invite-body { gap: 10px; } .share-channel { font-size: 10px; } }
|
|
|
+</style>
|