1325 lines
31 KiB
Vue
1325 lines
31 KiB
Vue
<script setup>
|
||
/**
|
||
* 邀请新用户页面
|
||
* 合伙人及以上用户可见,用于邀请新用户并获取佣金
|
||
*/
|
||
import { ref, computed, onMounted } from 'vue'
|
||
import { onShow, onPullDownRefresh, onReachBottom, onShareAppMessage } from '@dcloudio/uni-app'
|
||
import { useUserStore, USER_LEVEL } from '@/store/user.js'
|
||
import { useAuth } from '@/composables/useAuth.js'
|
||
import { useNavbar } from '@/composables/useNavbar.js'
|
||
import {
|
||
getInviteInfo,
|
||
getQrcode,
|
||
getRecordList,
|
||
getCommission,
|
||
applyWithdraw,
|
||
getWithdrawList
|
||
} from '@/api/invite.js'
|
||
import Empty from '@/components/Empty/index.vue'
|
||
import Loading from '@/components/Loading/index.vue'
|
||
|
||
const userStore = useUserStore()
|
||
const { checkLogin } = useAuth()
|
||
const { statusBarHeight, navbarHeight, totalNavbarHeight } = useNavbar()
|
||
|
||
// 提现状态常量
|
||
const WITHDRAW_STATUS = {
|
||
APPLYING: 1, // 申请中
|
||
PROCESSING: 2, // 提现中
|
||
CANCELLED: 3, // 已取消
|
||
COMPLETED: 4 // 已提现
|
||
}
|
||
|
||
// 页面状态
|
||
const loading = ref(false)
|
||
const refreshing = ref(false)
|
||
|
||
// 佣金信息
|
||
const commissionInfo = ref({
|
||
withdrawn: 0, // 已提现金额
|
||
pending: 0, // 待提现金额
|
||
total: 0 // 总佣金
|
||
})
|
||
|
||
// 邀请记录列表
|
||
const recordList = ref([])
|
||
const page = ref(1)
|
||
const pageSize = ref(10)
|
||
const total = ref(0)
|
||
const noMore = ref(false)
|
||
|
||
// 弹窗状态
|
||
const showRulePopup = ref(false)
|
||
const showQrcodePopup = ref(false)
|
||
const showWithdrawPopup = ref(false)
|
||
const showWithdrawRecordPopup = ref(false)
|
||
|
||
// 二维码数据
|
||
const qrcodeUrl = ref('')
|
||
const qrcodeLoading = ref(false)
|
||
|
||
// 提现表单
|
||
const withdrawAmount = ref('')
|
||
const withdrawLoading = ref(false)
|
||
|
||
// 提现记录
|
||
const withdrawRecordList = ref([])
|
||
const withdrawRecordPage = ref(1)
|
||
const withdrawRecordTotal = ref(0)
|
||
const withdrawRecordNoMore = ref(false)
|
||
const withdrawRecordLoading = ref(false)
|
||
|
||
// 计算属性
|
||
const isPartner = computed(() => userStore.isPartner)
|
||
const isEmpty = computed(() => !loading.value && recordList.value.length === 0)
|
||
const hasMore = computed(() => recordList.value.length < total.value)
|
||
|
||
// 导航栏样式
|
||
const navbarStyle = computed(() => ({
|
||
paddingTop: statusBarHeight.value + 'px',
|
||
height: totalNavbarHeight.value + 'px'
|
||
}))
|
||
|
||
/**
|
||
* 获取提现状态文本
|
||
*/
|
||
function getWithdrawStatusText(status) {
|
||
const statusMap = {
|
||
[WITHDRAW_STATUS.APPLYING]: '申请中',
|
||
[WITHDRAW_STATUS.PROCESSING]: '提现中',
|
||
[WITHDRAW_STATUS.CANCELLED]: '已取消',
|
||
[WITHDRAW_STATUS.COMPLETED]: '已提现'
|
||
}
|
||
return statusMap[status] || '未知状态'
|
||
}
|
||
|
||
/**
|
||
* 获取提现状态样式类
|
||
*/
|
||
function getWithdrawStatusClass(status) {
|
||
const classMap = {
|
||
[WITHDRAW_STATUS.APPLYING]: 'status-applying',
|
||
[WITHDRAW_STATUS.PROCESSING]: 'status-processing',
|
||
[WITHDRAW_STATUS.CANCELLED]: 'status-cancelled',
|
||
[WITHDRAW_STATUS.COMPLETED]: 'status-completed'
|
||
}
|
||
return classMap[status] || ''
|
||
}
|
||
|
||
/**
|
||
* 格式化日期
|
||
*/
|
||
function formatDate(dateStr) {
|
||
if (!dateStr) return ''
|
||
const date = new Date(dateStr)
|
||
const year = date.getFullYear()
|
||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||
const day = String(date.getDate()).padStart(2, '0')
|
||
return `${year}-${month}-${day}`
|
||
}
|
||
|
||
/**
|
||
* 格式化金额
|
||
*/
|
||
function formatAmount(amount) {
|
||
if (amount === undefined || amount === null) return '0.00'
|
||
return Number(amount).toFixed(2)
|
||
}
|
||
|
||
/**
|
||
* 加载佣金信息
|
||
*/
|
||
async function loadCommissionInfo() {
|
||
try {
|
||
const res = await getCommission()
|
||
if (res.code === 0 && res.data) {
|
||
commissionInfo.value = {
|
||
withdrawn: res.data.withdrawn || 0,
|
||
pending: res.data.pending || 0,
|
||
total: res.data.total || 0
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('获取佣金信息失败:', error)
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 加载邀请记录列表
|
||
*/
|
||
async function loadRecordList(isRefresh = false) {
|
||
if (loading.value) return
|
||
|
||
if (isRefresh) {
|
||
page.value = 1
|
||
noMore.value = false
|
||
}
|
||
|
||
loading.value = true
|
||
|
||
try {
|
||
const res = await getRecordList({
|
||
page: page.value,
|
||
pageSize: pageSize.value
|
||
})
|
||
|
||
if (res.code === 0 && res.data) {
|
||
const list = res.data.list || []
|
||
total.value = res.data.total || 0
|
||
|
||
if (isRefresh) {
|
||
recordList.value = list
|
||
} else {
|
||
recordList.value = [...recordList.value, ...list]
|
||
}
|
||
|
||
noMore.value = recordList.value.length >= total.value
|
||
} else {
|
||
uni.showToast({
|
||
title: res.message || '获取邀请记录失败',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
} catch (error) {
|
||
console.error('获取邀请记录失败:', error)
|
||
uni.showToast({
|
||
title: '网络错误,请重试',
|
||
icon: 'none'
|
||
})
|
||
} finally {
|
||
loading.value = false
|
||
refreshing.value = false
|
||
uni.stopPullDownRefresh()
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 加载提现记录
|
||
*/
|
||
async function loadWithdrawRecordList(isRefresh = false) {
|
||
if (withdrawRecordLoading.value) return
|
||
|
||
if (isRefresh) {
|
||
withdrawRecordPage.value = 1
|
||
withdrawRecordNoMore.value = false
|
||
}
|
||
|
||
withdrawRecordLoading.value = true
|
||
|
||
try {
|
||
const res = await getWithdrawList({
|
||
page: withdrawRecordPage.value,
|
||
pageSize: 10
|
||
})
|
||
|
||
if (res.code === 0 && res.data) {
|
||
const list = res.data.list || []
|
||
withdrawRecordTotal.value = res.data.total || 0
|
||
|
||
if (isRefresh) {
|
||
withdrawRecordList.value = list
|
||
} else {
|
||
withdrawRecordList.value = [...withdrawRecordList.value, ...list]
|
||
}
|
||
|
||
withdrawRecordNoMore.value = withdrawRecordList.value.length >= withdrawRecordTotal.value
|
||
}
|
||
} catch (error) {
|
||
console.error('获取提现记录失败:', error)
|
||
} finally {
|
||
withdrawRecordLoading.value = false
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 显示规则说明弹窗
|
||
*/
|
||
function handleShowRule() {
|
||
showRulePopup.value = true
|
||
}
|
||
|
||
/**
|
||
* 关闭规则说明弹窗
|
||
*/
|
||
function handleCloseRule() {
|
||
showRulePopup.value = false
|
||
}
|
||
|
||
/**
|
||
* 生成二维码
|
||
*/
|
||
async function handleGenerateQrcode() {
|
||
showQrcodePopup.value = true
|
||
|
||
if (qrcodeUrl.value) return
|
||
|
||
qrcodeLoading.value = true
|
||
|
||
try {
|
||
const res = await getQrcode()
|
||
if (res.code === 0 && res.data) {
|
||
qrcodeUrl.value = res.data.qrcodeUrl || res.data.url || ''
|
||
} else {
|
||
uni.showToast({
|
||
title: res.message || '生成二维码失败',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
} catch (error) {
|
||
console.error('生成二维码失败:', error)
|
||
uni.showToast({
|
||
title: '网络错误,请重试',
|
||
icon: 'none'
|
||
})
|
||
} finally {
|
||
qrcodeLoading.value = false
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 关闭二维码弹窗
|
||
*/
|
||
function handleCloseQrcode() {
|
||
showQrcodePopup.value = false
|
||
}
|
||
|
||
/**
|
||
* 保存二维码到相册
|
||
*/
|
||
function handleSaveQrcode() {
|
||
if (!qrcodeUrl.value) {
|
||
uni.showToast({
|
||
title: '二维码未加载',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
|
||
uni.saveImageToPhotosAlbum({
|
||
filePath: qrcodeUrl.value,
|
||
success: () => {
|
||
uni.showToast({
|
||
title: '保存成功',
|
||
icon: 'success'
|
||
})
|
||
},
|
||
fail: (err) => {
|
||
console.error('保存失败:', err)
|
||
if (err.errMsg.includes('auth deny')) {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '需要您授权保存图片到相册',
|
||
confirmText: '去设置',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
uni.openSetting()
|
||
}
|
||
}
|
||
})
|
||
} else {
|
||
uni.showToast({
|
||
title: '保存失败',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 分享链接
|
||
*/
|
||
function handleShare() {
|
||
// 触发微信分享
|
||
}
|
||
|
||
/**
|
||
* 显示申请提现弹窗
|
||
*/
|
||
function handleShowWithdraw() {
|
||
withdrawAmount.value = ''
|
||
showWithdrawPopup.value = true
|
||
}
|
||
|
||
/**
|
||
* 关闭申请提现弹窗
|
||
*/
|
||
function handleCloseWithdraw() {
|
||
showWithdrawPopup.value = false
|
||
}
|
||
|
||
/**
|
||
* 提交提现申请
|
||
*/
|
||
async function handleSubmitWithdraw() {
|
||
const amount = parseInt(withdrawAmount.value)
|
||
|
||
if (!amount || amount < 1) {
|
||
uni.showToast({
|
||
title: '最低提现1元',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
|
||
if (amount > commissionInfo.value.pending) {
|
||
uni.showToast({
|
||
title: '超出待提现金额',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
|
||
withdrawLoading.value = true
|
||
|
||
try {
|
||
const res = await applyWithdraw(amount)
|
||
if (res.code === 0) {
|
||
uni.showToast({
|
||
title: '申请已提交',
|
||
icon: 'success'
|
||
})
|
||
showWithdrawPopup.value = false
|
||
// 刷新佣金信息
|
||
loadCommissionInfo()
|
||
} else {
|
||
uni.showToast({
|
||
title: res.message || '申请失败',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
} catch (error) {
|
||
console.error('提现申请失败:', error)
|
||
uni.showToast({
|
||
title: '网络错误,请重试',
|
||
icon: 'none'
|
||
})
|
||
} finally {
|
||
withdrawLoading.value = false
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 显示提现记录弹窗
|
||
*/
|
||
function handleShowWithdrawRecord() {
|
||
showWithdrawRecordPopup.value = true
|
||
loadWithdrawRecordList(true)
|
||
}
|
||
|
||
/**
|
||
* 关闭提现记录弹窗
|
||
*/
|
||
function handleCloseWithdrawRecord() {
|
||
showWithdrawRecordPopup.value = false
|
||
}
|
||
|
||
/**
|
||
* 提现记录滚动到底部加载更多
|
||
*/
|
||
function handleWithdrawRecordScrollToLower() {
|
||
if (!withdrawRecordNoMore.value && !withdrawRecordLoading.value) {
|
||
withdrawRecordPage.value++
|
||
loadWithdrawRecordList()
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 下拉刷新
|
||
*/
|
||
onPullDownRefresh(() => {
|
||
refreshing.value = true
|
||
loadCommissionInfo()
|
||
loadRecordList(true)
|
||
})
|
||
|
||
/**
|
||
* 上拉加载更多
|
||
*/
|
||
onReachBottom(() => {
|
||
if (!noMore.value && !loading.value) {
|
||
page.value++
|
||
loadRecordList()
|
||
}
|
||
})
|
||
|
||
/**
|
||
* 分享给好友
|
||
*/
|
||
onShareAppMessage(() => {
|
||
return {
|
||
title: '邀请您加入学业邑规划',
|
||
path: `/pages/index/index?inviteUid=${userStore.uid}`,
|
||
imageUrl: '/static/logo.png'
|
||
}
|
||
})
|
||
|
||
/**
|
||
* 页面显示时检查权限并加载数据
|
||
*/
|
||
onShow(() => {
|
||
userStore.restoreFromStorage()
|
||
|
||
// 检查登录状态
|
||
if (!checkLogin()) return
|
||
|
||
// 检查是否是合伙人
|
||
if (!userStore.isPartner) {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '该功能仅限合伙人使用',
|
||
showCancel: false,
|
||
confirmText: '返回',
|
||
success: () => {
|
||
uni.navigateBack()
|
||
}
|
||
})
|
||
return
|
||
}
|
||
|
||
loadCommissionInfo()
|
||
loadRecordList(true)
|
||
})
|
||
|
||
/**
|
||
* 页面加载
|
||
*/
|
||
onMounted(() => {
|
||
userStore.restoreFromStorage()
|
||
})
|
||
</script>
|
||
|
||
<template>
|
||
<view class="invite-page">
|
||
<!-- 自定义导航栏 -->
|
||
<view class="custom-navbar" :style="navbarStyle">
|
||
<view class="navbar-content" :style="{ height: navbarHeight + 'px' }">
|
||
<view class="navbar-back" @click="() => uni.navigateBack()">
|
||
<view class="back-icon"></view>
|
||
</view>
|
||
<text class="navbar-title">邀请新用户</text>
|
||
<view class="navbar-right" @click="handleShowRule">
|
||
<text class="rule-btn">规则说明</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 导航栏占位 -->
|
||
<view class="navbar-placeholder" :style="{ height: totalNavbarHeight + 'px' }"></view>
|
||
|
||
<!-- 页面内容 -->
|
||
<view class="page-content">
|
||
<!-- 邀请操作区域 -->
|
||
<view class="invite-actions">
|
||
<view class="action-btn qrcode-btn" @click="handleGenerateQrcode">
|
||
<text class="action-icon">📱</text>
|
||
<text class="action-text">生成二维码</text>
|
||
</view>
|
||
<button class="action-btn share-btn" open-type="share">
|
||
<text class="action-icon">🔗</text>
|
||
<text class="action-text">分享链接</text>
|
||
</button>
|
||
</view>
|
||
|
||
<!-- 佣金信息区域 -->
|
||
<view class="commission-section">
|
||
<view class="commission-card">
|
||
<view class="commission-item">
|
||
<text class="commission-label">已提现</text>
|
||
<text class="commission-value">¥{{ formatAmount(commissionInfo.withdrawn) }}</text>
|
||
</view>
|
||
<view class="commission-divider"></view>
|
||
<view class="commission-item">
|
||
<text class="commission-label">待提现</text>
|
||
<text class="commission-value highlight">¥{{ formatAmount(commissionInfo.pending) }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="commission-actions">
|
||
<view class="commission-btn" @click="handleShowWithdraw">
|
||
<text>申请提现</text>
|
||
</view>
|
||
<view class="commission-btn outline" @click="handleShowWithdrawRecord">
|
||
<text>查看提现记录</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 邀请记录区域 -->
|
||
<view class="record-section">
|
||
<view class="section-header">
|
||
<text class="section-title">我的邀请记录</text>
|
||
<text class="section-count">共{{ total }}人</text>
|
||
</view>
|
||
|
||
<!-- 加载中 -->
|
||
<Loading type="page" :loading="loading && recordList.length === 0" />
|
||
|
||
<!-- 邀请记录列表 -->
|
||
<view class="record-list" v-if="!isEmpty">
|
||
<view
|
||
class="record-item"
|
||
v-for="record in recordList"
|
||
:key="record.id"
|
||
>
|
||
<view class="record-avatar">
|
||
<image
|
||
class="avatar-img"
|
||
:src="record.avatar || '/static/logo.png'"
|
||
mode="aspectFill"
|
||
/>
|
||
</view>
|
||
<view class="record-info">
|
||
<view class="record-name">{{ record.nickname || '用户' }}</view>
|
||
<view class="record-uid">UID: {{ record.uid || '--' }}</view>
|
||
<view class="record-date">注册日期: {{ formatDate(record.registerTime) }}</view>
|
||
</view>
|
||
<view class="record-commission">
|
||
<text class="commission-amount">+¥{{ formatAmount(record.commission) }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 加载更多 -->
|
||
<Loading
|
||
type="more"
|
||
:loading="loading && recordList.length > 0"
|
||
:noMore="noMore"
|
||
noMoreText="没有更多记录了"
|
||
/>
|
||
</view>
|
||
|
||
<!-- 空状态 -->
|
||
<Empty
|
||
v-if="isEmpty"
|
||
text="暂无邀请记录"
|
||
:showButton="false"
|
||
/>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 规则说明弹窗 -->
|
||
<view v-if="showRulePopup" class="popup-mask" @click="handleCloseRule">
|
||
<view class="popup-container rule-popup" @click.stop>
|
||
<view class="popup-header">
|
||
<text class="popup-title">规则说明</text>
|
||
<view class="popup-close" @click="handleCloseRule">
|
||
<text>×</text>
|
||
</view>
|
||
</view>
|
||
<scroll-view class="popup-body" scroll-y>
|
||
<view class="rule-content">
|
||
<view class="rule-item">
|
||
<text class="rule-num">1.</text>
|
||
<text class="rule-text">合伙人及以上用户可通过专属链接或二维码邀请新用户注册。</text>
|
||
</view>
|
||
<view class="rule-item">
|
||
<text class="rule-num">2.</text>
|
||
<text class="rule-text">被邀请用户通过您的链接注册后,将自动绑定为您的下级用户。</text>
|
||
</view>
|
||
<view class="rule-item">
|
||
<text class="rule-num">3.</text>
|
||
<text class="rule-text">下级用户在小程序内成功支付后,您可获得每笔订单40%的佣金。</text>
|
||
</view>
|
||
<view class="rule-item">
|
||
<text class="rule-num">4.</text>
|
||
<text class="rule-text">若您有上级用户,每笔订单您获得30%佣金,您的上级获得10%佣金。</text>
|
||
</view>
|
||
<view class="rule-item">
|
||
<text class="rule-num">5.</text>
|
||
<text class="rule-text">佣金可申请提现,最低提现金额为1元,仅支持整数金额。</text>
|
||
</view>
|
||
<view class="rule-item">
|
||
<text class="rule-num">6.</text>
|
||
<text class="rule-text">提现申请提交后,将在1-3个工作日内处理。</text>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
<view class="popup-footer">
|
||
<view class="popup-btn primary" @click="handleCloseRule">
|
||
<text>我知道了</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 二维码弹窗 -->
|
||
<view v-if="showQrcodePopup" class="popup-mask" @click="handleCloseQrcode">
|
||
<view class="popup-container qrcode-popup" @click.stop>
|
||
<view class="popup-header">
|
||
<text class="popup-title">邀请二维码</text>
|
||
<view class="popup-close" @click="handleCloseQrcode">
|
||
<text>×</text>
|
||
</view>
|
||
</view>
|
||
<view class="popup-body">
|
||
<view class="qrcode-wrapper">
|
||
<Loading type="inline" :loading="qrcodeLoading" v-if="qrcodeLoading" />
|
||
<image
|
||
v-else-if="qrcodeUrl"
|
||
class="qrcode-img"
|
||
:src="qrcodeUrl"
|
||
mode="aspectFit"
|
||
/>
|
||
<view v-else class="qrcode-placeholder">
|
||
<text>二维码加载失败</text>
|
||
</view>
|
||
</view>
|
||
<text class="qrcode-tip">扫描二维码邀请新用户</text>
|
||
</view>
|
||
<view class="popup-footer">
|
||
<view class="popup-btn primary" @click="handleSaveQrcode">
|
||
<text>保存到相册</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 申请提现弹窗 -->
|
||
<view v-if="showWithdrawPopup" class="popup-mask" @click="handleCloseWithdraw">
|
||
<view class="popup-container withdraw-popup" @click.stop>
|
||
<view class="popup-header">
|
||
<text class="popup-title">申请提现</text>
|
||
<view class="popup-close" @click="handleCloseWithdraw">
|
||
<text>×</text>
|
||
</view>
|
||
</view>
|
||
<view class="popup-body">
|
||
<view class="withdraw-info">
|
||
<text class="withdraw-label">可提现金额</text>
|
||
<text class="withdraw-available">¥{{ formatAmount(commissionInfo.pending) }}</text>
|
||
</view>
|
||
<view class="withdraw-input-wrapper">
|
||
<text class="input-prefix">¥</text>
|
||
<input
|
||
class="withdraw-input"
|
||
type="number"
|
||
v-model="withdrawAmount"
|
||
placeholder="请输入提现金额"
|
||
placeholder-class="input-placeholder"
|
||
/>
|
||
</view>
|
||
<text class="withdraw-tip">最低提现1元,仅支持整数金额</text>
|
||
</view>
|
||
<view class="popup-footer">
|
||
<view
|
||
class="popup-btn primary"
|
||
:class="{ disabled: withdrawLoading }"
|
||
@click="handleSubmitWithdraw"
|
||
>
|
||
<text>{{ withdrawLoading ? '提交中...' : '申请提现' }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 提现记录弹窗 -->
|
||
<view v-if="showWithdrawRecordPopup" class="popup-mask" @click="handleCloseWithdrawRecord">
|
||
<view class="popup-container withdraw-record-popup" @click.stop>
|
||
<view class="popup-header">
|
||
<text class="popup-title">提现记录</text>
|
||
<view class="popup-close" @click="handleCloseWithdrawRecord">
|
||
<text>×</text>
|
||
</view>
|
||
</view>
|
||
<scroll-view
|
||
class="popup-body record-scroll"
|
||
scroll-y
|
||
@scrolltolower="handleWithdrawRecordScrollToLower"
|
||
>
|
||
<Loading type="inline" :loading="withdrawRecordLoading && withdrawRecordList.length === 0" />
|
||
|
||
<view class="withdraw-record-list" v-if="withdrawRecordList.length > 0">
|
||
<view
|
||
class="withdraw-record-item"
|
||
v-for="record in withdrawRecordList"
|
||
:key="record.id"
|
||
>
|
||
<view class="record-left">
|
||
<text class="record-amount">¥{{ formatAmount(record.amount) }}</text>
|
||
<text class="record-time">{{ formatDate(record.createTime) }}</text>
|
||
</view>
|
||
<view class="record-right">
|
||
<text
|
||
class="record-status"
|
||
:class="getWithdrawStatusClass(record.status)"
|
||
>
|
||
{{ getWithdrawStatusText(record.status) }}
|
||
</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="empty-record" v-else-if="!withdrawRecordLoading">
|
||
<text>暂无提现记录</text>
|
||
</view>
|
||
|
||
<Loading
|
||
type="more"
|
||
:loading="withdrawRecordLoading && withdrawRecordList.length > 0"
|
||
:noMore="withdrawRecordNoMore"
|
||
noMoreText="没有更多记录了"
|
||
/>
|
||
</scroll-view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<style lang="scss" scoped>
|
||
@import '@/styles/variables.scss';
|
||
|
||
.invite-page {
|
||
min-height: 100vh;
|
||
background-color: $bg-color;
|
||
}
|
||
|
||
// 自定义导航栏
|
||
.custom-navbar {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
background-color: $bg-white;
|
||
z-index: 999;
|
||
|
||
.navbar-content {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 0 $spacing-lg;
|
||
|
||
.navbar-back {
|
||
width: 60rpx;
|
||
height: 60rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
.back-icon {
|
||
width: 20rpx;
|
||
height: 20rpx;
|
||
border-left: 4rpx solid $text-color;
|
||
border-bottom: 4rpx solid $text-color;
|
||
transform: rotate(45deg);
|
||
margin-left: 8rpx;
|
||
}
|
||
}
|
||
|
||
.navbar-title {
|
||
font-size: 34rpx;
|
||
font-weight: $font-weight-medium;
|
||
color: $text-color;
|
||
}
|
||
|
||
.navbar-right {
|
||
.rule-btn {
|
||
font-size: $font-size-sm;
|
||
color: $primary-color;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.navbar-placeholder {
|
||
width: 100%;
|
||
}
|
||
|
||
// 页面内容
|
||
.page-content {
|
||
padding: $spacing-lg;
|
||
padding-bottom: calc(#{$spacing-lg} + env(safe-area-inset-bottom));
|
||
}
|
||
|
||
// 邀请操作区域
|
||
.invite-actions {
|
||
display: flex;
|
||
gap: $spacing-lg;
|
||
margin-bottom: $spacing-lg;
|
||
|
||
.action-btn {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background-color: $bg-white;
|
||
border-radius: $border-radius-lg;
|
||
padding: $spacing-lg;
|
||
border: none;
|
||
|
||
&::after {
|
||
border: none;
|
||
}
|
||
|
||
&:active {
|
||
opacity: 0.8;
|
||
}
|
||
|
||
.action-icon {
|
||
font-size: 48rpx;
|
||
margin-bottom: $spacing-sm;
|
||
}
|
||
|
||
.action-text {
|
||
font-size: $font-size-md;
|
||
color: $text-color;
|
||
}
|
||
}
|
||
|
||
.qrcode-btn {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
|
||
.action-text {
|
||
color: $text-white;
|
||
}
|
||
}
|
||
|
||
.share-btn {
|
||
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
|
||
|
||
.action-text {
|
||
color: $text-white;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 佣金信息区域
|
||
.commission-section {
|
||
background-color: $bg-white;
|
||
border-radius: $border-radius-lg;
|
||
padding: $spacing-lg;
|
||
margin-bottom: $spacing-lg;
|
||
|
||
.commission-card {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: $spacing-lg;
|
||
|
||
.commission-item {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
|
||
.commission-label {
|
||
font-size: $font-size-sm;
|
||
color: $text-secondary;
|
||
margin-bottom: $spacing-xs;
|
||
}
|
||
|
||
.commission-value {
|
||
font-size: $font-size-xxl;
|
||
font-weight: $font-weight-bold;
|
||
color: $text-color;
|
||
|
||
&.highlight {
|
||
color: $error-color;
|
||
}
|
||
}
|
||
}
|
||
|
||
.commission-divider {
|
||
width: 1rpx;
|
||
height: 80rpx;
|
||
background-color: $border-color;
|
||
}
|
||
}
|
||
|
||
.commission-actions {
|
||
display: flex;
|
||
gap: $spacing-md;
|
||
|
||
.commission-btn {
|
||
flex: 1;
|
||
height: 72rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background-color: $primary-color;
|
||
border-radius: 36rpx;
|
||
|
||
&:active {
|
||
opacity: 0.8;
|
||
}
|
||
|
||
text {
|
||
font-size: $font-size-md;
|
||
color: $text-white;
|
||
}
|
||
|
||
&.outline {
|
||
background-color: transparent;
|
||
border: 2rpx solid $primary-color;
|
||
|
||
text {
|
||
color: $primary-color;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 邀请记录区域
|
||
.record-section {
|
||
background-color: $bg-white;
|
||
border-radius: $border-radius-lg;
|
||
padding: $spacing-lg;
|
||
|
||
.section-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
margin-bottom: $spacing-lg;
|
||
|
||
.section-title {
|
||
font-size: $font-size-lg;
|
||
font-weight: $font-weight-medium;
|
||
color: $text-color;
|
||
}
|
||
|
||
.section-count {
|
||
font-size: $font-size-sm;
|
||
color: $text-secondary;
|
||
}
|
||
}
|
||
|
||
.record-list {
|
||
.record-item {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: $spacing-md 0;
|
||
border-bottom: 1rpx solid $border-light;
|
||
|
||
&:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.record-avatar {
|
||
margin-right: $spacing-md;
|
||
|
||
.avatar-img {
|
||
width: 80rpx;
|
||
height: 80rpx;
|
||
border-radius: 50%;
|
||
background-color: $bg-gray;
|
||
}
|
||
}
|
||
|
||
.record-info {
|
||
flex: 1;
|
||
|
||
.record-name {
|
||
font-size: $font-size-md;
|
||
font-weight: $font-weight-medium;
|
||
color: $text-color;
|
||
margin-bottom: 4rpx;
|
||
}
|
||
|
||
.record-uid {
|
||
font-size: $font-size-xs;
|
||
color: $text-secondary;
|
||
margin-bottom: 4rpx;
|
||
}
|
||
|
||
.record-date {
|
||
font-size: $font-size-xs;
|
||
color: $text-placeholder;
|
||
}
|
||
}
|
||
|
||
.record-commission {
|
||
.commission-amount {
|
||
font-size: $font-size-md;
|
||
font-weight: $font-weight-medium;
|
||
color: $error-color;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 弹窗通用样式
|
||
.popup-mask {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background-color: $bg-mask;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
z-index: 1000;
|
||
}
|
||
|
||
.popup-container {
|
||
width: 600rpx;
|
||
max-height: 80vh;
|
||
background-color: $bg-white;
|
||
border-radius: $border-radius-lg;
|
||
overflow: hidden;
|
||
|
||
.popup-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: $spacing-lg;
|
||
border-bottom: 1rpx solid $border-light;
|
||
|
||
.popup-title {
|
||
font-size: $font-size-lg;
|
||
font-weight: $font-weight-medium;
|
||
color: $text-color;
|
||
}
|
||
|
||
.popup-close {
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
text {
|
||
font-size: 48rpx;
|
||
color: $text-placeholder;
|
||
line-height: 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
.popup-body {
|
||
padding: $spacing-lg;
|
||
}
|
||
|
||
.popup-footer {
|
||
padding: $spacing-lg;
|
||
border-top: 1rpx solid $border-light;
|
||
|
||
.popup-btn {
|
||
height: 80rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border-radius: 40rpx;
|
||
|
||
&.primary {
|
||
background-color: $primary-color;
|
||
|
||
text {
|
||
font-size: $font-size-lg;
|
||
color: $text-white;
|
||
}
|
||
|
||
&:active {
|
||
opacity: 0.8;
|
||
}
|
||
|
||
&.disabled {
|
||
background-color: #CCCCCC;
|
||
pointer-events: none;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 规则说明弹窗
|
||
.rule-popup {
|
||
.popup-body {
|
||
max-height: 500rpx;
|
||
|
||
.rule-content {
|
||
.rule-item {
|
||
display: flex;
|
||
margin-bottom: $spacing-md;
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.rule-num {
|
||
font-size: $font-size-md;
|
||
color: $primary-color;
|
||
font-weight: $font-weight-medium;
|
||
margin-right: $spacing-xs;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.rule-text {
|
||
font-size: $font-size-md;
|
||
color: $text-color;
|
||
line-height: 1.6;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 二维码弹窗
|
||
.qrcode-popup {
|
||
.popup-body {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
|
||
.qrcode-wrapper {
|
||
width: 400rpx;
|
||
height: 400rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background-color: $bg-gray;
|
||
border-radius: $border-radius-md;
|
||
margin-bottom: $spacing-md;
|
||
|
||
.qrcode-img {
|
||
width: 360rpx;
|
||
height: 360rpx;
|
||
}
|
||
|
||
.qrcode-placeholder {
|
||
text {
|
||
font-size: $font-size-md;
|
||
color: $text-placeholder;
|
||
}
|
||
}
|
||
}
|
||
|
||
.qrcode-tip {
|
||
font-size: $font-size-sm;
|
||
color: $text-secondary;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 申请提现弹窗
|
||
.withdraw-popup {
|
||
.popup-body {
|
||
.withdraw-info {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
margin-bottom: $spacing-lg;
|
||
|
||
.withdraw-label {
|
||
font-size: $font-size-md;
|
||
color: $text-secondary;
|
||
}
|
||
|
||
.withdraw-available {
|
||
font-size: $font-size-lg;
|
||
font-weight: $font-weight-medium;
|
||
color: $error-color;
|
||
}
|
||
}
|
||
|
||
.withdraw-input-wrapper {
|
||
display: flex;
|
||
align-items: center;
|
||
background-color: $bg-gray;
|
||
border-radius: $border-radius-md;
|
||
padding: 0 $spacing-md;
|
||
margin-bottom: $spacing-sm;
|
||
|
||
.input-prefix {
|
||
font-size: $font-size-xl;
|
||
font-weight: $font-weight-medium;
|
||
color: $text-color;
|
||
margin-right: $spacing-xs;
|
||
}
|
||
|
||
.withdraw-input {
|
||
flex: 1;
|
||
height: 88rpx;
|
||
font-size: $font-size-lg;
|
||
color: $text-color;
|
||
}
|
||
|
||
.input-placeholder {
|
||
color: $text-placeholder;
|
||
}
|
||
}
|
||
|
||
.withdraw-tip {
|
||
font-size: $font-size-xs;
|
||
color: $text-placeholder;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 提现记录弹窗
|
||
.withdraw-record-popup {
|
||
.record-scroll {
|
||
max-height: 600rpx;
|
||
|
||
.withdraw-record-list {
|
||
.withdraw-record-item {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: $spacing-md 0;
|
||
border-bottom: 1rpx solid $border-light;
|
||
|
||
&:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.record-left {
|
||
.record-amount {
|
||
display: block;
|
||
font-size: $font-size-lg;
|
||
font-weight: $font-weight-medium;
|
||
color: $text-color;
|
||
margin-bottom: 4rpx;
|
||
}
|
||
|
||
.record-time {
|
||
display: block;
|
||
font-size: $font-size-xs;
|
||
color: $text-placeholder;
|
||
}
|
||
}
|
||
|
||
.record-right {
|
||
.record-status {
|
||
font-size: $font-size-sm;
|
||
padding: 4rpx 16rpx;
|
||
border-radius: $border-radius-sm;
|
||
|
||
&.status-applying {
|
||
color: $warning-color;
|
||
background-color: rgba(250, 173, 20, 0.1);
|
||
}
|
||
|
||
&.status-processing {
|
||
color: $primary-color;
|
||
background-color: rgba(74, 144, 226, 0.1);
|
||
}
|
||
|
||
&.status-cancelled {
|
||
color: $text-placeholder;
|
||
background-color: rgba(153, 153, 153, 0.1);
|
||
}
|
||
|
||
&.status-completed {
|
||
color: $success-color;
|
||
background-color: rgba(82, 196, 26, 0.1);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.empty-record {
|
||
padding: 60rpx 0;
|
||
text-align: center;
|
||
|
||
text {
|
||
font-size: $font-size-md;
|
||
color: $text-placeholder;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style>
|