1796 lines
44 KiB
Vue
1796 lines
44 KiB
Vue
<template>
|
||
<page-meta :page-style="pageStyle"></page-meta>
|
||
<view class="page">
|
||
|
||
<!-- 固定导航栏 -->
|
||
<view class="navbar-fixed" :style="{ background: navbarBgColor }">
|
||
<image src="/static/ic_back.png" class="back-btn" @click="goBack" mode=""></image>
|
||
<text class="navbar-title">{{ $t('invite.title') }}</text>
|
||
</view>
|
||
|
||
<!-- 顶部红色奖励区域 -->
|
||
<view class="reward-header">
|
||
<image src="/static/new_bg1.png" class="bg-image" mode="scaleToFill"></image>
|
||
|
||
<!-- 奖励内容 -->
|
||
<view class="reward-content">
|
||
<text class="reward-title">{{ $t('invite.rewardTitle') }}</text>
|
||
<view class="reward-desc-box">
|
||
<text class="reward-desc">{{ $t('invite.rewardDesc') }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 参与步骤 -->
|
||
<view class="steps-section">
|
||
<view class="section-title-row">
|
||
<view class="title-line"></view>
|
||
<text class="section-title">{{ $t('invite.stepsTitle') }}</text>
|
||
<view class="title-line"></view>
|
||
</view>
|
||
|
||
<view class="step-item">
|
||
<view class="step-icon step-icon-1">
|
||
<image src="/static/new_user.png" class="step-img" mode="widthFix"></image>
|
||
</view>
|
||
<text class="step-text">{{ $t('invite.step1') }}</text>
|
||
</view>
|
||
|
||
<view class="step-item">
|
||
<view class="step-icon step-icon-2">
|
||
<image src="/static/red_box.png" class="step-img" mode="widthFix"></image>
|
||
</view>
|
||
<text class="step-text">{{ $t('invite.step2') }}</text>
|
||
</view>
|
||
|
||
<view class="step-item">
|
||
<view class="step-icon step-icon-3">
|
||
<image src="/static/ic_wallet.png" class="step-img" mode="widthFix"></image>
|
||
</view>
|
||
<text class="step-text">{{ $t('invite.step3') }}</text>
|
||
</view>
|
||
|
||
<view class="detail-link" @click="showDetail">
|
||
<text class="detail-text">{{ $t('invite.viewDetail') }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 操作按钮 -->
|
||
<view class="action-buttons">
|
||
<view class="action-btn qrcode-btn" @click="generateQRCode">
|
||
<text class="btn-text">{{ $t('invite.generateQRCode') }}</text>
|
||
</view>
|
||
<!-- #ifdef MP-WEIXIN -->
|
||
<button class="action-btn share-btn share-btn-native" open-type="share">
|
||
<text class="btn-text">{{ $t('invite.shareToFriend') }}</text>
|
||
</button>
|
||
<!-- #endif -->
|
||
<!-- #ifndef MP-WEIXIN -->
|
||
<view class="action-btn share-btn" @click="shareToFriend">
|
||
<text class="btn-text">{{ $t('invite.shareToFriend') }}</text>
|
||
</view>
|
||
<!-- #endif -->
|
||
</view>
|
||
|
||
<!-- 提现记录 -->
|
||
<view class="record-section">
|
||
<view class="record-header" @click="goToWithdrawDetail">
|
||
<text class="record-title">{{ $t('invite.withdrawRecord') }}</text>
|
||
<view class="record-more">
|
||
<text class="more-text">{{ $t('invite.withdrawPeriod') }}</text>
|
||
<image src="/static/arrow_right3.png" class="arrow-icon" mode=""></image>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="record-content">
|
||
<image src="/static/new_bg2.png" class="record-bg-image" mode="scaleToFill"></image>
|
||
|
||
<view class="reward-cards">
|
||
<view class="reward-card" v-for="(item, index) in withdrawRecords" :key="index">
|
||
<text class="reward-amount">{{ item.amount }}{{ $t('common.currency') }}</text>
|
||
<text class="reward-status">{{ item.status }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="apply-withdraw-btn" @click="applyWithdraw">
|
||
<text class="apply-text">{{ $t('invite.applyWithdraw') }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 邀请记录 -->
|
||
<view class="invite-record-section">
|
||
<view class="invite-record-header">
|
||
<text class="record-title">{{ $t('invite.inviteRecord') }}</text>
|
||
</view>
|
||
|
||
<view class="invite-record-content">
|
||
<image src="/static/approved.png" class="content-bg-stamp" mode="aspectFit"></image>
|
||
|
||
<view class="table-header">
|
||
<text class="table-col">{{ $t('invite.username') }}</text>
|
||
<text class="table-col">{{ $t('invite.uid') }}</text>
|
||
<text class="table-col">{{ $t('invite.inviteTime') }}</text>
|
||
<text class="table-col">{{ $t('invite.paid') }}</text>
|
||
</view>
|
||
|
||
<view class="table-body">
|
||
<view class="table-row" v-for="(item, index) in inviteRecords" :key="index">
|
||
<text class="table-cell">{{ item.username }}</text>
|
||
<text class="table-cell">{{ item.uid }}</text>
|
||
<text class="table-cell">{{ item.time }}</text>
|
||
<view class="table-cell status-cell">
|
||
<text v-if="item.paid && item.amount" class="paid-amount">¥{{ item.amount }}</text>
|
||
<text v-else class="unpaid-text">¥0</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view v-if="inviteRecords.length === 0" class="empty-state">
|
||
<text class="empty-text">{{ $t('common.noData') }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 提现明细弹窗 -->
|
||
<up-popup :show="showWithdrawModal" mode="center" :round="20" :overlay="true" :closeOnClickOverlay="true" bgColor="#ffffff" @close="closeWithdrawModal">
|
||
<view class="modal-content">
|
||
<view class="modal-header">
|
||
<text class="modal-title">{{ $t('invite.withdrawDetail') }}</text>
|
||
<image src="/static/ic_colse.png" class="close-icon" @click="closeWithdrawModal" mode=""></image>
|
||
</view>
|
||
|
||
<view class="modal-table">
|
||
<view class="modal-table-header">
|
||
<text class="modal-table-col">{{ $t('invite.time') }}</text>
|
||
<text class="modal-table-col">{{ $t('invite.amount') }}</text>
|
||
<text class="modal-table-col">{{ $t('invite.status') }}</text>
|
||
</view>
|
||
|
||
<view class="modal-table-body">
|
||
<view class="modal-table-row" v-for="(item, index) in withdrawDetailList" :key="index">
|
||
<text class="modal-table-cell">{{ item.time }}</text>
|
||
<text class="modal-table-cell">¥{{ item.amount }}</text>
|
||
<text class="modal-table-cell">{{ item.status }}</text>
|
||
</view>
|
||
<view v-if="withdrawDetailList.length === 0" class="modal-empty-state">
|
||
<text class="modal-empty-text">{{ $t('common.noData') }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</up-popup>
|
||
|
||
<!-- 二维码弹窗 -->
|
||
<up-popup :show="showQRCodeModal" mode="center" :round="20" :overlay="true" :closeOnClickOverlay="true" bgColor="#ffffff" @close="closeQRCodeModal">
|
||
<view class="qrcode-modal-content">
|
||
<text class="qrcode-modal-title">{{ $t('invite.qrcodeTitle') || '邀请好友,赢现金' }}</text>
|
||
<view class="qrcode-box">
|
||
<!-- 微信小程序码 -->
|
||
<image v-if="wxQrcodeImage" :src="wxQrcodeImage" class="wx-qrcode-image" mode="aspectFit"></image>
|
||
<!-- 小程序未发布时显示提示 -->
|
||
<view v-else-if="useLocalQrcode" class="unpublished-tip">
|
||
<image src="/static/ic_warning.png" class="tip-icon" mode="aspectFit"></image>
|
||
<text class="tip-text">小程序未发布</text>
|
||
<text class="tip-subtext">暂无法生成二维码</text>
|
||
</view>
|
||
<!-- 加载中 -->
|
||
<view v-else-if="qrcodeLoading" class="qrcode-loading">
|
||
<text>加载中...</text>
|
||
</view>
|
||
<!-- 错误提示 -->
|
||
<text v-else-if="qrcodeError" class="qrcode-error">{{ qrcodeError }}</text>
|
||
</view>
|
||
<text v-if="useLocalQrcode" class="qrcode-tip">请使用下方分享功能邀请好友</text>
|
||
<view class="qrcode-actions">
|
||
<!-- #ifdef MP-WEIXIN -->
|
||
<button class="qrcode-action-btn share-action-btn share-btn-native" open-type="share">
|
||
<text class="action-btn-text">{{ $t('invite.shareToFriend') || '分享给好友' }}</text>
|
||
</button>
|
||
<!-- #endif -->
|
||
<!-- #ifndef MP-WEIXIN -->
|
||
<view class="qrcode-action-btn share-action-btn" @click="shareQRCodeToFriend">
|
||
<text class="action-btn-text">{{ $t('invite.shareToFriend') || '分享给好友' }}</text>
|
||
</view>
|
||
<!-- #endif -->
|
||
<view class="qrcode-action-btn save-action-btn" @click="saveQRCodeImage" v-if="!useLocalQrcode">
|
||
<text class="action-btn-text">{{ $t('invite.saveImage') || '保存图片' }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</up-popup>
|
||
|
||
<!-- 申请提现弹窗 - 原生写法 -->
|
||
<view class="apply-modal-overlay" v-if="showApplyModal" @click="closeApplyModal">
|
||
<view class="apply-modal-wrapper" @click.stop>
|
||
<view class="apply-modal-content">
|
||
<!-- 红色标题栏 -->
|
||
<view class="apply-modal-header">
|
||
<text class="apply-modal-title">{{ $t('invite.withdrawApplication') }} {{ applyStep }}/2</text>
|
||
</view>
|
||
|
||
<!-- 第一步:输入金额 -->
|
||
<view v-if="applyStep === 1" class="apply-step-content">
|
||
<image src="/static/new_bg2.png" class="step-bg-image" mode="aspectFill"></image>
|
||
|
||
<text class="step-label">{{ $t('invite.selectCurrency') || '选择货币类型' }}</text>
|
||
<view class="currency-methods">
|
||
<view class="currency-method" :class="{ active: withdrawCurrency === 'CNY' }"
|
||
@click="selectCurrency('CNY')">
|
||
<text class="method-text">¥ {{ $t('invite.currencyCNY') || '人民币' }}</text>
|
||
</view>
|
||
<view class="currency-method" :class="{ active: withdrawCurrency === 'PHP' }"
|
||
@click="selectCurrency('PHP')">
|
||
<text class="method-text">₱ {{ $t('invite.currencyPHP') || '比索' }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<text class="step-label">{{ $t('invite.enterAmount') }}</text>
|
||
<view class="amount-input-row">
|
||
<input class="amount-input" type="number" v-model="withdrawAmount"
|
||
:placeholder="$t('invite.enterPlaceholder')" />
|
||
<text class="currency-text">{{ withdrawCurrency === 'CNY' ? '¥' : '₱' }}</text>
|
||
</view>
|
||
<text class="amount-hint">{{ $t('invite.amountHint') }}</text>
|
||
|
||
<view class="apply-btn" @click="nextStep">
|
||
<text class="apply-btn-text">{{ $t('invite.nextStep') }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 第二步:选择收款方式 -->
|
||
<view v-if="applyStep === 2" class="apply-step-content">
|
||
<image src="/static/new_bg2.png" class="step-bg-image" mode="aspectFill"></image>
|
||
<text class="step-label">1.{{ $t('invite.selectPaymentMethod') }}</text>
|
||
<view class="payment-methods">
|
||
<view class="payment-method" :class="{ active: paymentMethod === 'wechat' }"
|
||
@click="selectPaymentMethod('wechat')">
|
||
<text class="method-text">{{ $t('invite.wechat') }}</text>
|
||
</view>
|
||
<view class="payment-method" :class="{ active: paymentMethod === 'alipay' }"
|
||
@click="selectPaymentMethod('alipay')">
|
||
<text class="method-text">{{ $t('invite.alipay') }}</text>
|
||
</view>
|
||
<view class="payment-method" :class="{ active: paymentMethod === 'bank' }"
|
||
@click="selectPaymentMethod('bank')">
|
||
<text class="method-text">{{ $t('invite.bankCard') }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 微信/支付宝:上传收款码 -->
|
||
<view v-if="paymentMethod !== 'bank'">
|
||
<text class="step-label">2.{{ $t('invite.uploadQRCode') }}</text>
|
||
<view class="upload-area" @click="uploadQRCode">
|
||
<image v-if="qrcodeImage" :src="qrcodeImage" class="uploaded-image" mode="aspectFit">
|
||
</image>
|
||
<text v-else class="upload-icon">+</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 银行卡:填写银行卡信息 -->
|
||
<view v-if="paymentMethod === 'bank'">
|
||
<text class="step-label">2.{{ $t('invite.enterBankInfo') }}</text>
|
||
|
||
<view class="form-item">
|
||
<text class="form-label">{{ $t('invite.bankCardNumber') }}</text>
|
||
<input class="form-input" v-model="bankCardNumber"
|
||
:placeholder="$t('invite.enterBankCardNumber')" />
|
||
</view>
|
||
|
||
<view class="form-item">
|
||
<text class="form-label">{{ $t('invite.cardholderName') }}</text>
|
||
<input class="form-input" v-model="cardholderName"
|
||
:placeholder="$t('invite.enterCardholderName')" />
|
||
</view>
|
||
|
||
<view class="form-item">
|
||
<text class="form-label">{{ $t('invite.bankName') }}</text>
|
||
<input class="form-input" v-model="bankName" :placeholder="$t('invite.enterBankName')" />
|
||
</view>
|
||
|
||
<view class="form-item">
|
||
<text class="form-label">{{ $t('invite.swiftCode') }} ({{ $t('invite.optional') }})</text>
|
||
<input class="form-input" v-model="swiftCode" :placeholder="$t('invite.enterSwiftCode')" />
|
||
</view>
|
||
</view>
|
||
|
||
<view class="apply-btn" @click="submitWithdraw">
|
||
<text class="apply-btn-text">{{ $t('invite.applyWithdraw') }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import {
|
||
AppServer
|
||
} from '@/modules/api/AppServer.js'
|
||
const appServer = new AppServer()
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
navbarBgColor: 'transparent',
|
||
scrollTop: 0,
|
||
showWithdrawModal: false,
|
||
showApplyModal: false,
|
||
showQRCodeModal: false,
|
||
showQRCodeContent: false, // 控制二维码内容显示
|
||
qrcodeDataUrl: '',
|
||
qrcodeValue: '', // 二维码内容(本地生成用)
|
||
wxQrcodeImage: '', // 微信小程序码图片(base64)
|
||
useLocalQrcode: false, // 是否使用本地二维码组件
|
||
qrcodeLoading: false, // 小程序码加载状态
|
||
qrcodeError: '', // 小程序码错误信息
|
||
appLogo: '', // 应用logo,用于分享图片
|
||
applyStep: 1,
|
||
withdrawAmount: '',
|
||
withdrawCurrency: 'CNY',
|
||
paymentMethod: 'wechat',
|
||
qrcodeImage: '',
|
||
bankCardNumber: '',
|
||
cardholderName: '',
|
||
bankName: '',
|
||
swiftCode: '',
|
||
withdrawRecords: [],
|
||
withdrawDetailList: [],
|
||
inviteRecords: [],
|
||
// 佣金统计
|
||
commissionStats: {
|
||
totalInvites: 0,
|
||
paidInvites: 0,
|
||
totalCommission: '0.00',
|
||
availableBalance: '0.00',
|
||
invitationCode: ''
|
||
},
|
||
loading: false,
|
||
inviteRules: '' // 邀请规则说明(从后台配置获取)
|
||
}
|
||
},
|
||
computed: {
|
||
// 弹窗显示时禁止页面滚动
|
||
pageStyle() {
|
||
if (this.showQRCodeModal || this.showWithdrawModal || this.showApplyModal) {
|
||
return 'overflow: hidden;'
|
||
}
|
||
return ''
|
||
}
|
||
},
|
||
onLoad() {
|
||
this.loadData()
|
||
},
|
||
// 微信小程序分享配置
|
||
onShareAppMessage() {
|
||
const inviteCode = this.commissionStats.invitationCode || ''
|
||
// 使用应用logo作为分享图片
|
||
// 注意:微信小程序分享图片支持本地路径和网络路径(https)
|
||
// 开发环境下http图片可能无法显示,使用本地图片作为备选
|
||
let shareImage = '/static/new_bg1.png'
|
||
if (this.appLogo && this.appLogo.startsWith('http')) {
|
||
shareImage = this.appLogo
|
||
}
|
||
console.log('分享图片路径:', shareImage, 'appLogo:', this.appLogo)
|
||
return {
|
||
title: '邀请你加入,一起赚佣金!',
|
||
path: `/pages/index/index?inviteCode=${inviteCode}`,
|
||
imageUrl: shareImage
|
||
}
|
||
},
|
||
// 分享到朋友圈(微信小程序)
|
||
onShareTimeline() {
|
||
const inviteCode = this.commissionStats.invitationCode || ''
|
||
let shareImage = '/static/new_bg1.png'
|
||
if (this.appLogo && this.appLogo.startsWith('http')) {
|
||
shareImage = this.appLogo
|
||
}
|
||
return {
|
||
title: '邀请你加入,一起赚佣金!',
|
||
query: `inviteCode=${inviteCode}`,
|
||
imageUrl: shareImage
|
||
}
|
||
},
|
||
methods: {
|
||
// 加载数据
|
||
async loadData() {
|
||
this.loading = true
|
||
try {
|
||
await Promise.all([
|
||
this.loadCommissionStats(),
|
||
this.loadCommissionRecords(),
|
||
this.loadWithdrawRecords(),
|
||
this.loadAppConfig()
|
||
])
|
||
} catch (error) {
|
||
console.error('加载数据失败:', error)
|
||
} finally {
|
||
this.loading = false
|
||
}
|
||
},
|
||
|
||
// 加载应用配置(从globalData获取logo和邀请规则)
|
||
loadAppConfig() {
|
||
try {
|
||
const app = getApp()
|
||
if (app && app.globalData && app.globalData.config) {
|
||
const config = app.globalData.config
|
||
if (config.app_logo) {
|
||
this.appLogo = app.getConfigImageUrl('app_logo')
|
||
console.log('从globalData获取到应用logo:', this.appLogo)
|
||
}
|
||
// 获取邀请规则说明
|
||
if (config.invite_rules) {
|
||
this.inviteRules = config.invite_rules
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('获取应用配置失败:', error)
|
||
}
|
||
},
|
||
|
||
// 加载佣金统计
|
||
async loadCommissionStats() {
|
||
try {
|
||
const res = await appServer.GetCommissionStats()
|
||
console.log('GetCommissionStats response:', res)
|
||
// 后端返回格式: { code: 0, message: "", data: {...} }
|
||
if (res && res.code === 0 && res.data) {
|
||
this.commissionStats = res.data
|
||
console.log('commissionStats updated:', this.commissionStats)
|
||
// 更新提现记录显示
|
||
this.updateWithdrawDisplay()
|
||
// 预先设置二维码内容,用于分享(使用小程序路径)
|
||
const inviteCode = res.data.invitationCode || ''
|
||
this.qrcodeValue = `/pages/index/index?inviteCode=${inviteCode}`
|
||
}
|
||
} catch (error) {
|
||
console.error('获取佣金统计失败:', error)
|
||
}
|
||
},
|
||
|
||
// 加载佣金记录(改为加载邀请记录)
|
||
async loadCommissionRecords() {
|
||
try {
|
||
// 使用邀请记录API,显示所有被邀请的用户(包括未支付的)
|
||
const res = await appServer.GetInvitationRecords()
|
||
// 后端返回格式: { success: true, data: { records: [...] } }
|
||
if (res && res.success && res.data && res.data.records) {
|
||
this.inviteRecords = res.data.records.map(item => ({
|
||
username: item.invitee?.nickname || '-',
|
||
uid: item.invitee?.uid || '-',
|
||
time: this.formatDate(item.createdAt),
|
||
paid: item.firstPaymentAt != null,
|
||
amount: item.rewardAmount ? parseFloat(item.rewardAmount) : 0
|
||
}))
|
||
}
|
||
} catch (error) {
|
||
console.error('获取邀请记录失败:', error)
|
||
}
|
||
},
|
||
|
||
// 加载提现记录
|
||
async loadWithdrawRecords() {
|
||
try {
|
||
const res = await appServer.GetWithdrawals({
|
||
page: 1,
|
||
limit: 10
|
||
})
|
||
// 后端返回格式: { code: 0, message: "", data: {...} }
|
||
if (res && res.code === 0 && res.data && res.data.records) {
|
||
this.withdrawDetailList = res.data.records.map(item => ({
|
||
time: this.formatDate(item.createdAt),
|
||
amount: item.amount,
|
||
status: this.getWithdrawStatusText(item.status)
|
||
}))
|
||
}
|
||
} catch (error) {
|
||
console.error('获取提现记录失败:', error)
|
||
}
|
||
},
|
||
|
||
// 更新提现显示
|
||
updateWithdrawDisplay() {
|
||
// 显示待提现、处理中、已完成的金额
|
||
this.withdrawRecords = [{
|
||
amount: this.commissionStats.availableBalance || '0',
|
||
status: this.$t('invite.statusWaiting')
|
||
}]
|
||
},
|
||
|
||
// 格式化日期
|
||
formatDate(dateStr) {
|
||
if (!dateStr) return '-'
|
||
const date = new Date(dateStr)
|
||
return `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`
|
||
},
|
||
|
||
// 获取提现状态文本
|
||
getWithdrawStatusText(status) {
|
||
const statusMap = {
|
||
'waiting': this.$t('invite.statusWaiting'),
|
||
'processing': this.$t('invite.statusProcessing'),
|
||
'completed': this.$t('invite.statusCompleted'),
|
||
'rejected': this.$t('invite.statusRejected') || '已拒绝'
|
||
}
|
||
return statusMap[status] || status
|
||
},
|
||
goBack() {
|
||
uni.navigateBack()
|
||
},
|
||
showDetail() {
|
||
uni.showModal({
|
||
title: '规则说明',
|
||
content: this.inviteRules || this.$t('invite.ruleContent'),
|
||
showCancel: false
|
||
})
|
||
},
|
||
async generateQRCode() {
|
||
console.log('generateQRCode called, current state:', {
|
||
wxQrcodeImage: this.wxQrcodeImage,
|
||
qrcodeValue: this.qrcodeValue,
|
||
useLocalQrcode: this.useLocalQrcode,
|
||
invitationCode: this.commissionStats.invitationCode
|
||
})
|
||
|
||
// 如果已有小程序码,直接显示
|
||
if (this.wxQrcodeImage || (this.useLocalQrcode && this.commissionStats.invitationCode)) {
|
||
this.showQRCodeModal = true
|
||
return
|
||
}
|
||
|
||
// 显示弹窗并开始加载
|
||
this.showQRCodeModal = true
|
||
this.qrcodeLoading = true
|
||
this.qrcodeError = ''
|
||
|
||
try {
|
||
// 调用后端API获取微信小程序码
|
||
const res = await appServer.GetMiniProgramQRCode({ width: 430 })
|
||
console.log('获取小程序码响应:', res)
|
||
|
||
if (res && res.code === 0 && res.data) {
|
||
// 更新邀请码(后端返回的最新邀请码)
|
||
if (res.data.invitationCode) {
|
||
this.commissionStats.invitationCode = res.data.invitationCode
|
||
}
|
||
|
||
if (res.data.qrcodeUrl) {
|
||
// 使用微信小程序码
|
||
this.wxQrcodeImage = res.data.qrcodeUrl
|
||
this.useLocalQrcode = false
|
||
} else if (res.data.useLocalQrcode) {
|
||
// 小程序未发布,显示邀请码
|
||
this.qrcodeValue = res.data.qrcodeContent
|
||
this.useLocalQrcode = true
|
||
this.showQRCodeContent = true
|
||
}
|
||
} else {
|
||
this.qrcodeError = res?.message || '生成小程序码失败'
|
||
}
|
||
} catch (error) {
|
||
console.error('生成小程序码失败:', error)
|
||
this.qrcodeError = '网络错误,请重试'
|
||
} finally {
|
||
this.qrcodeLoading = false
|
||
}
|
||
},
|
||
closeQRCodeModal() {
|
||
this.showQRCodeModal = false
|
||
},
|
||
shareQRCodeToFriend() {
|
||
// 分享给好友
|
||
// #ifdef MP-WEIXIN
|
||
// 微信小程序使用 button 的 open-type="share" 来触发分享
|
||
// 这里使用 uni.share 作为备选方案
|
||
// #endif
|
||
uni.showToast({
|
||
title: this.$t('invite.shareSuccess') || '请使用右上角分享',
|
||
icon: 'none'
|
||
})
|
||
},
|
||
saveQRCodeImage() {
|
||
// 使用本地二维码组件
|
||
if (this.useLocalQrcode && this.$refs.uQrcode) {
|
||
this.$refs.uQrcode.toTempFilePath({
|
||
success: (res) => {
|
||
uni.saveImageToPhotosAlbum({
|
||
filePath: res.tempFilePath,
|
||
success: () => {
|
||
uni.showToast({
|
||
title: this.$t('invite.saveSuccess') || '保存成功',
|
||
icon: 'success'
|
||
})
|
||
},
|
||
fail: (err) => {
|
||
console.error('保存图片失败:', err)
|
||
if (err.errMsg && err.errMsg.includes('auth deny')) {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '需要您授权保存图片到相册',
|
||
success: (modalRes) => {
|
||
if (modalRes.confirm) {
|
||
uni.openSetting()
|
||
}
|
||
}
|
||
})
|
||
} else {
|
||
uni.showToast({
|
||
title: '保存失败',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
}
|
||
})
|
||
},
|
||
fail: (err) => {
|
||
console.error('获取二维码图片失败:', err)
|
||
uni.showToast({
|
||
title: '获取二维码失败',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
})
|
||
return
|
||
}
|
||
|
||
// 使用微信小程序码
|
||
if (!this.wxQrcodeImage) {
|
||
uni.showToast({
|
||
title: '小程序码加载中,请稍候',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
|
||
// 将 base64 图片保存到相册
|
||
const base64Data = this.wxQrcodeImage.replace(/^data:image\/\w+;base64,/, '')
|
||
const filePath = `${wx.env.USER_DATA_PATH}/qrcode_${Date.now()}.png`
|
||
|
||
const fs = uni.getFileSystemManager()
|
||
fs.writeFile({
|
||
filePath: filePath,
|
||
data: base64Data,
|
||
encoding: 'base64',
|
||
success: () => {
|
||
uni.saveImageToPhotosAlbum({
|
||
filePath: filePath,
|
||
success: () => {
|
||
uni.showToast({
|
||
title: this.$t('invite.saveSuccess') || '保存成功',
|
||
icon: 'success'
|
||
})
|
||
},
|
||
fail: (err) => {
|
||
console.error('保存图片失败:', err)
|
||
if (err.errMsg && err.errMsg.includes('auth deny')) {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '需要您授权保存图片到相册',
|
||
success: (modalRes) => {
|
||
if (modalRes.confirm) {
|
||
uni.openSetting()
|
||
}
|
||
}
|
||
})
|
||
} else {
|
||
uni.showToast({
|
||
title: '保存失败',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
}
|
||
})
|
||
},
|
||
fail: (err) => {
|
||
console.error('写入文件失败:', err)
|
||
uni.showToast({
|
||
title: '保存失败',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
})
|
||
},
|
||
shareToFriend() {
|
||
uni.share({
|
||
provider: 'weixin',
|
||
scene: 'WXSceneSession',
|
||
type: 0,
|
||
title: this.$t('invite.shareTitle'),
|
||
success: () => {
|
||
uni.showToast({
|
||
title: this.$t('invite.shareSuccess'),
|
||
icon: 'success'
|
||
})
|
||
}
|
||
})
|
||
},
|
||
goToWithdrawDetail() {
|
||
// 打开提现明细弹窗,数据已在loadWithdrawRecords中加载
|
||
this.showWithdrawModal = true
|
||
},
|
||
closeWithdrawModal() {
|
||
this.showWithdrawModal = false
|
||
},
|
||
applyWithdraw() {
|
||
// 打开申请提现弹窗
|
||
this.applyStep = 1
|
||
this.withdrawAmount = ''
|
||
this.withdrawCurrency = 'CNY'
|
||
this.paymentMethod = 'wechat'
|
||
this.qrcodeImage = ''
|
||
this.bankCardNumber = ''
|
||
this.cardholderName = ''
|
||
this.bankName = ''
|
||
this.swiftCode = ''
|
||
this.showApplyModal = true
|
||
},
|
||
closeApplyModal() {
|
||
this.showApplyModal = false
|
||
},
|
||
nextStep() {
|
||
// 解析提现金额,支持小数点后两位
|
||
const amount = parseFloat(this.withdrawAmount)
|
||
|
||
// 验证金额是否有效
|
||
if (!this.withdrawAmount || isNaN(amount)) {
|
||
uni.showToast({
|
||
title: this.$t('invite.enterAmountError'),
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
|
||
// 最低1元
|
||
if (amount < 1) {
|
||
uni.showToast({
|
||
title: this.$t('invite.amountTooLow') || '低于1元,无法申请提现',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
|
||
// 最高不超过待提现金额
|
||
const availableBalance = parseFloat(this.commissionStats.availableBalance || '0')
|
||
if (amount > availableBalance) {
|
||
uni.showToast({
|
||
title: this.$t('invite.amountExceedsBalance') || '超出可提现金额',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
|
||
// 限制小数点后两位
|
||
const formattedAmount = Math.floor(amount * 100) / 100
|
||
this.withdrawAmount = formattedAmount.toString()
|
||
|
||
this.applyStep = 2
|
||
},
|
||
selectPaymentMethod(method) {
|
||
this.paymentMethod = method
|
||
},
|
||
selectCurrency(currency) {
|
||
this.withdrawCurrency = currency
|
||
},
|
||
uploadQRCode() {
|
||
uni.chooseImage({
|
||
count: 1,
|
||
success: (res) => {
|
||
this.qrcodeImage = res.tempFilePaths[0]
|
||
}
|
||
})
|
||
},
|
||
async submitWithdraw() {
|
||
// 验证微信/支付宝收款码
|
||
if (this.paymentMethod !== 'bank' && !this.qrcodeImage) {
|
||
uni.showToast({
|
||
title: this.$t('invite.uploadQRCodeError'),
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
|
||
// 验证银行卡信息
|
||
if (this.paymentMethod === 'bank') {
|
||
if (!this.bankCardNumber || !this.cardholderName || !this.bankName) {
|
||
uni.showToast({
|
||
title: this.$t('invite.bankInfoError'),
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
}
|
||
|
||
// 构建支付详情
|
||
let paymentDetails = {}
|
||
if (this.paymentMethod === 'bank') {
|
||
paymentDetails = {
|
||
bankCardNumber: this.bankCardNumber,
|
||
cardholderName: this.cardholderName,
|
||
bankName: this.bankName,
|
||
swiftCode: this.swiftCode || undefined
|
||
}
|
||
} else {
|
||
// 微信/支付宝需要上传收款码图片
|
||
try {
|
||
const uploadRes = await appServer.UploadImage(this.qrcodeImage)
|
||
// 后端返回格式: { code: 0, message: "", data: {...} }
|
||
if (uploadRes && uploadRes.code === 0 && uploadRes.data) {
|
||
paymentDetails = {
|
||
qrcodeUrl: uploadRes.data.url
|
||
}
|
||
} else {
|
||
uni.showToast({
|
||
title: '上传收款码失败',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
} catch (error) {
|
||
console.error('上传收款码失败:', error)
|
||
uni.showToast({
|
||
title: '上传收款码失败',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
}
|
||
|
||
// 提交提现申请
|
||
try {
|
||
const res = await appServer.CreateWithdrawal({
|
||
amount: parseFloat(this.withdrawAmount),
|
||
currency: this.withdrawCurrency,
|
||
paymentMethod: this.paymentMethod,
|
||
paymentDetails: paymentDetails
|
||
})
|
||
|
||
// 后端返回格式: { code: 0, message: "", data: {...} }
|
||
if (res && res.code === 0) {
|
||
uni.showToast({
|
||
title: this.$t('invite.applySuccess'),
|
||
icon: 'success'
|
||
})
|
||
this.closeApplyModal()
|
||
// 刷新数据
|
||
this.loadData()
|
||
} else {
|
||
uni.showToast({
|
||
title: res.error?.message || '提现申请失败',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
} catch (error) {
|
||
console.error('提现申请失败:', error)
|
||
uni.showToast({
|
||
title: '提现申请失败',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
},
|
||
handleScroll(e) {
|
||
// 页面滚动事件在 uni-app 中需要使用 onPageScroll
|
||
}
|
||
},
|
||
onPageScroll(e) {
|
||
const scrollTop = e.scrollTop
|
||
// 滚动距离超过 100px 时,导航栏背景从透明渐变到红色
|
||
if (scrollTop > 100) {
|
||
this.navbarBgColor = 'linear-gradient(135deg, #FF3B4E 0%, #FF6B7A 100%)'
|
||
} else {
|
||
// 根据滚动距离计算透明度
|
||
const opacity = scrollTop / 100
|
||
this.navbarBgColor = `rgba(255, 59, 78, ${opacity})`
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.page {
|
||
min-height: 100vh;
|
||
background-color: #F3F4F8;
|
||
}
|
||
|
||
.navbar-fixed {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
z-index: 100;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding-top: 44px;
|
||
height: 88rpx;
|
||
transition: background 0.3s ease;
|
||
|
||
.back-btn {
|
||
position: absolute;
|
||
left: 30rpx;
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
filter: brightness(0) invert(1);
|
||
}
|
||
|
||
.navbar-title {
|
||
font-size: 36rpx;
|
||
font-weight: 500;
|
||
color: #FFFFFF;
|
||
}
|
||
}
|
||
|
||
.reward-header {
|
||
position: relative;
|
||
height: 550rpx;
|
||
background-color: #FF3B4E;
|
||
overflow: hidden;
|
||
|
||
.bg-image {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: cover;
|
||
}
|
||
|
||
.reward-content {
|
||
position: relative;
|
||
z-index: 5;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
min-height: 550rpx;
|
||
padding: 80rpx 30rpx 0;
|
||
|
||
.reward-title {
|
||
font-size: 60rpx;
|
||
font-weight: bold;
|
||
color: #FFFFFF;
|
||
text-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.3);
|
||
margin-bottom: 60rpx;
|
||
letter-spacing: 2rpx;
|
||
text-align: center;
|
||
word-break: break-word;
|
||
max-width: 100%;
|
||
line-height: 1.3;
|
||
}
|
||
|
||
.reward-desc-box {
|
||
background-color: rgba(255, 255, 255, 0.98);
|
||
border-radius: 60rpx;
|
||
padding: 24rpx 50rpx;
|
||
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.1);
|
||
max-width: 90%;
|
||
|
||
.reward-desc {
|
||
font-size: 26rpx;
|
||
color: #333333;
|
||
line-height: 1.8;
|
||
text-align: center;
|
||
word-break: break-word;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
.steps-section {
|
||
background-color: #FFFFFF;
|
||
margin: 30rpx;
|
||
border-radius: 20rpx;
|
||
padding: 40rpx 30rpx;
|
||
|
||
.section-title-row {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-bottom: 40rpx;
|
||
|
||
.title-line {
|
||
width: 60rpx;
|
||
height: 2rpx;
|
||
background-color: #333333;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 30rpx;
|
||
font-weight: bold;
|
||
color: #333333;
|
||
margin: 0 20rpx;
|
||
white-space: nowrap;
|
||
}
|
||
}
|
||
|
||
.step-item {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
margin-left: 60rpx;
|
||
margin-bottom: 30rpx;
|
||
|
||
.step-icon {
|
||
width: 74rpx;
|
||
height: 74rpx;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-right: 24rpx;
|
||
flex-shrink: 0;
|
||
|
||
.step-img {
|
||
width: 74rpx;
|
||
height: 74rpx;
|
||
}
|
||
}
|
||
|
||
.step-text {
|
||
font-size: 26rpx;
|
||
color: #333333;
|
||
flex: 1;
|
||
line-height: 1.6;
|
||
word-break: break-word;
|
||
padding-top: 10rpx;
|
||
}
|
||
}
|
||
|
||
.detail-link {
|
||
text-align: center;
|
||
margin-top: 20rpx;
|
||
|
||
.detail-text {
|
||
font-size: 26rpx;
|
||
color: #007AFF;
|
||
text-decoration: underline;
|
||
}
|
||
}
|
||
}
|
||
|
||
.action-buttons {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
padding: 0 30rpx;
|
||
margin-bottom: 30rpx;
|
||
gap: 20rpx;
|
||
|
||
.action-btn {
|
||
flex: 1;
|
||
min-height: 50rpx;
|
||
border-radius: 44rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 20rpx 10rpx;
|
||
|
||
&.qrcode-btn {
|
||
background: linear-gradient(135deg, #FF3B4E 0%, #FF6B7A 100%);
|
||
}
|
||
|
||
&.share-btn {
|
||
background: linear-gradient(135deg, #FF6B7A 0%, #FF3B4E 100%);
|
||
}
|
||
|
||
// 微信原生分享按钮样式重置
|
||
&.share-btn-native {
|
||
border: none;
|
||
margin: 0;
|
||
line-height: normal;
|
||
|
||
&::after {
|
||
border: none;
|
||
}
|
||
}
|
||
|
||
.btn-text {
|
||
font-size: 28rpx;
|
||
font-weight: bold;
|
||
color: #FFFFFF;
|
||
text-align: center;
|
||
word-break: break-word;
|
||
line-height: 1.4;
|
||
}
|
||
}
|
||
}
|
||
|
||
.record-section {
|
||
margin: 0 30rpx 30rpx;
|
||
border-radius: 20rpx;
|
||
overflow: hidden;
|
||
|
||
.record-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
background: linear-gradient(135deg, #FF3B4E 0%, #FF6B7A 100%);
|
||
padding: 24rpx 30rpx;
|
||
|
||
.record-title {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #FFFFFF;
|
||
}
|
||
|
||
.record-more {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.more-text {
|
||
font-size: 24rpx;
|
||
color: #FFFFFF;
|
||
margin-right: 8rpx;
|
||
}
|
||
|
||
.arrow-icon {
|
||
width: 24rpx;
|
||
height: 24rpx;
|
||
filter: brightness(0) invert(1);
|
||
}
|
||
}
|
||
}
|
||
|
||
.record-content {
|
||
background-color: #FFFFFF;
|
||
padding: 50rpx 30rpx 40rpx;
|
||
border: 4rpx solid #FF3B4E;
|
||
border-top: none;
|
||
border-radius: 0 0 20rpx 20rpx;
|
||
position: relative;
|
||
overflow: hidden;
|
||
|
||
.record-bg-image {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
opacity: 1;
|
||
pointer-events: none;
|
||
z-index: 0;
|
||
}
|
||
|
||
.reward-cards {
|
||
position: relative;
|
||
z-index: 1;
|
||
display: flex;
|
||
justify-content: space-around;
|
||
margin-bottom: 40rpx;
|
||
position: relative;
|
||
|
||
.reward-card {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
position: relative;
|
||
|
||
&:not(:last-child)::after {
|
||
content: '';
|
||
position: absolute;
|
||
right: 0;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
width: 1rpx;
|
||
height: 80rpx;
|
||
background-color: #E5E5E5;
|
||
}
|
||
|
||
.reward-amount {
|
||
font-size: 48rpx;
|
||
font-weight: bold;
|
||
color: #FF3B4E;
|
||
margin-bottom: 16rpx;
|
||
}
|
||
|
||
.reward-status {
|
||
font-size: 26rpx;
|
||
color: #333333;
|
||
}
|
||
}
|
||
}
|
||
|
||
.apply-withdraw-btn {
|
||
background: linear-gradient(135deg, #FF3B4E 0%, #FF6B7A 100%);
|
||
height: 88rpx;
|
||
border-radius: 44rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
position: relative;
|
||
z-index: 1;
|
||
width: 70%;
|
||
margin: 0 auto;
|
||
|
||
.apply-text {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #FFFFFF;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.invite-record-section {
|
||
margin: 0 30rpx 50rpx;
|
||
border-radius: 20rpx;
|
||
overflow: hidden;
|
||
padding-bottom: 50rpx;
|
||
|
||
.invite-record-header {
|
||
background: linear-gradient(135deg, #FF3B4E 0%, #FF6B7A 100%);
|
||
padding: 24rpx 30rpx;
|
||
|
||
.record-title {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #FFFFFF;
|
||
}
|
||
}
|
||
|
||
.invite-record-content {
|
||
background-color: #FFFFFF;
|
||
border: 4rpx solid #FF3B4E;
|
||
border-top: none;
|
||
border-radius: 0 0 20rpx 20rpx;
|
||
position: relative;
|
||
overflow: hidden;
|
||
|
||
.content-bg-stamp {
|
||
position: absolute;
|
||
right: 30rpx;
|
||
bottom: 30rpx;
|
||
width: 200rpx;
|
||
height: 200rpx;
|
||
opacity: 0.85;
|
||
pointer-events: none;
|
||
z-index: 0;
|
||
}
|
||
}
|
||
|
||
.table-header {
|
||
display: flex;
|
||
background-color: #FFFFFF;
|
||
padding: 24rpx 16rpx;
|
||
border-bottom: 2rpx solid #F0F0F0;
|
||
position: relative;
|
||
z-index: 1;
|
||
|
||
.table-col {
|
||
flex: 1;
|
||
font-size: 28rpx;
|
||
font-weight: bold;
|
||
color: #333333;
|
||
text-align: center;
|
||
}
|
||
}
|
||
|
||
.table-body {
|
||
position: relative;
|
||
z-index: 1;
|
||
|
||
.table-row {
|
||
display: flex;
|
||
padding: 24rpx 16rpx;
|
||
border-bottom: 1rpx solid #F0F0F0;
|
||
align-items: center;
|
||
|
||
&:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.table-cell {
|
||
flex: 1;
|
||
font-size: 26rpx;
|
||
color: #999999;
|
||
text-align: center;
|
||
|
||
&.status-cell {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
.paid-amount {
|
||
font-size: 28rpx;
|
||
font-weight: bold;
|
||
color: #333333;
|
||
}
|
||
|
||
.unpaid-text {
|
||
font-size: 28rpx;
|
||
font-weight: bold;
|
||
color: #999999;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.empty-state {
|
||
padding: 80rpx 0;
|
||
text-align: center;
|
||
|
||
.empty-text {
|
||
font-size: 28rpx;
|
||
color: #999999;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 提现明细弹窗
|
||
.modal-content {
|
||
width: 600rpx;
|
||
max-height: 70vh;
|
||
display: flex;
|
||
flex-direction: column;
|
||
box-sizing: border-box;
|
||
|
||
.modal-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 30rpx;
|
||
border-bottom: 1rpx solid #F0F0F0;
|
||
position: relative;
|
||
|
||
.modal-title {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #333333;
|
||
}
|
||
|
||
.close-icon {
|
||
position: absolute;
|
||
right: 30rpx;
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
}
|
||
}
|
||
|
||
.modal-table {
|
||
flex: 1;
|
||
overflow-y: auto;
|
||
|
||
.modal-table-header {
|
||
display: flex;
|
||
padding: 24rpx 20rpx;
|
||
background-color: #F8F8F8;
|
||
border-bottom: 1rpx solid #E5E5E5;
|
||
|
||
.modal-table-col {
|
||
flex: 1;
|
||
font-size: 28rpx;
|
||
font-weight: bold;
|
||
color: #333333;
|
||
text-align: center;
|
||
}
|
||
}
|
||
|
||
.modal-table-body {
|
||
.modal-table-row {
|
||
display: flex;
|
||
padding: 24rpx 20rpx;
|
||
border-bottom: 1rpx solid #F0F0F0;
|
||
|
||
&:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.modal-table-cell {
|
||
flex: 1;
|
||
font-size: 26rpx;
|
||
color: #666666;
|
||
text-align: center;
|
||
}
|
||
}
|
||
|
||
.modal-empty-state {
|
||
padding: 80rpx 0;
|
||
text-align: center;
|
||
|
||
.modal-empty-text {
|
||
font-size: 28rpx;
|
||
color: #999999;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 二维码弹窗
|
||
.qrcode-modal-content {
|
||
width: 600rpx;
|
||
padding: 40rpx 30rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
box-sizing: border-box;
|
||
position: relative;
|
||
overflow: hidden;
|
||
|
||
.qrcode-modal-title {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #333333;
|
||
margin-bottom: 30rpx;
|
||
text-align: center;
|
||
}
|
||
|
||
.qrcode-tip {
|
||
font-size: 24rpx;
|
||
color: #ff9800;
|
||
margin-bottom: 20rpx;
|
||
text-align: center;
|
||
}
|
||
|
||
.qrcode-box {
|
||
width: 440rpx;
|
||
min-height: 440rpx;
|
||
background-color: #FFFFFF;
|
||
border-radius: 16rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-bottom: 30rpx;
|
||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
|
||
position: relative;
|
||
overflow: hidden;
|
||
|
||
.wx-qrcode-image {
|
||
width: 400rpx;
|
||
height: 400rpx;
|
||
}
|
||
|
||
.unpublished-tip {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 40rpx;
|
||
|
||
.tip-icon {
|
||
width: 80rpx;
|
||
height: 80rpx;
|
||
margin-bottom: 20rpx;
|
||
opacity: 0.6;
|
||
}
|
||
|
||
.tip-text {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #999;
|
||
margin-bottom: 10rpx;
|
||
}
|
||
|
||
.tip-subtext {
|
||
font-size: 26rpx;
|
||
color: #bbb;
|
||
}
|
||
}
|
||
|
||
.qrcode-loading {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: #999;
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.qrcode-error {
|
||
color: #ff4d4f;
|
||
font-size: 26rpx;
|
||
text-align: center;
|
||
}
|
||
|
||
:deep(.u-qrcode__canvas) {
|
||
position: static !important;
|
||
left: auto !important;
|
||
top: auto !important;
|
||
z-index: 1 !important;
|
||
}
|
||
|
||
:deep(canvas) {
|
||
position: static !important;
|
||
left: auto !important;
|
||
top: auto !important;
|
||
}
|
||
}
|
||
|
||
.qrcode-actions {
|
||
display: flex;
|
||
gap: 30rpx;
|
||
width: 100%;
|
||
|
||
.qrcode-action-btn {
|
||
flex: 1;
|
||
height: 80rpx;
|
||
border-radius: 40rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
&.share-action-btn {
|
||
background: linear-gradient(135deg, #4ECDC4 0%, #44A08D 100%);
|
||
}
|
||
|
||
&.save-action-btn {
|
||
background: linear-gradient(135deg, #4ECDC4 0%, #44A08D 100%);
|
||
}
|
||
|
||
// 微信原生分享按钮样式重置
|
||
&.share-btn-native {
|
||
border: none;
|
||
padding: 0;
|
||
margin: 0;
|
||
line-height: 80rpx;
|
||
|
||
&::after {
|
||
border: none;
|
||
}
|
||
}
|
||
|
||
.action-btn-text {
|
||
font-size: 28rpx;
|
||
font-weight: bold;
|
||
color: #FFFFFF;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 申请提现弹窗 - 原生写法
|
||
.apply-modal-overlay {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background-color: rgba(0, 0, 0, 0.5);
|
||
z-index: 999;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.apply-modal-wrapper {
|
||
width: 650rpx;
|
||
max-width: 90vw;
|
||
max-height: 80vh;
|
||
background-color: #FFFFFF;
|
||
border-radius: 20rpx;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.apply-modal-content {
|
||
width: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
box-sizing: border-box;
|
||
|
||
.apply-modal-header {
|
||
background: linear-gradient(135deg, #FF3B4E 0%, #FF6B7A 100%);
|
||
padding: 30rpx 20rpx;
|
||
text-align: center;
|
||
flex-shrink: 0;
|
||
|
||
.apply-modal-title {
|
||
font-size: 30rpx;
|
||
font-weight: bold;
|
||
color: #FFFFFF;
|
||
word-break: keep-all;
|
||
}
|
||
}
|
||
|
||
.apply-step-content {
|
||
padding: 40rpx 30rpx;
|
||
position: relative;
|
||
background-color: #FFFFFF;
|
||
overflow: hidden;
|
||
flex: 1;
|
||
|
||
.step-bg-image {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
opacity: 0.85;
|
||
pointer-events: none;
|
||
z-index: 0;
|
||
}
|
||
|
||
.step-label {
|
||
font-size: 26rpx;
|
||
color: #333333;
|
||
font-weight: bold;
|
||
display: block;
|
||
margin-bottom: 20rpx;
|
||
position: relative;
|
||
z-index: 1;
|
||
line-height: 1.5;
|
||
word-break: break-word;
|
||
}
|
||
|
||
.amount-input-row {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-bottom: 16rpx;
|
||
position: relative;
|
||
z-index: 1;
|
||
|
||
.amount-input {
|
||
flex: 1;
|
||
height: 80rpx;
|
||
background-color: #FFFFFF;
|
||
border: 1rpx solid #E5E5E5;
|
||
border-radius: 12rpx;
|
||
padding: 0 20rpx;
|
||
font-size: 32rpx;
|
||
text-align: center;
|
||
}
|
||
|
||
.currency-text {
|
||
font-size: 32rpx;
|
||
color: #333333;
|
||
margin-left: 16rpx;
|
||
}
|
||
}
|
||
|
||
.amount-hint {
|
||
font-size: 24rpx;
|
||
color: #999999;
|
||
text-align: center;
|
||
display: block;
|
||
margin-bottom: 40rpx;
|
||
position: relative;
|
||
z-index: 1;
|
||
}
|
||
|
||
.currency-methods {
|
||
display: flex;
|
||
gap: 20rpx;
|
||
margin-bottom: 30rpx;
|
||
position: relative;
|
||
z-index: 1;
|
||
|
||
.currency-method {
|
||
flex: 1;
|
||
height: 80rpx;
|
||
background-color: #E8E8E8;
|
||
border-radius: 12rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 0 12rpx;
|
||
|
||
&.active {
|
||
background: linear-gradient(135deg, #FF3B4E 0%, #FF6B7A 100%);
|
||
|
||
.method-text {
|
||
color: #FFFFFF;
|
||
}
|
||
}
|
||
|
||
.method-text {
|
||
font-size: 28rpx;
|
||
color: #666666;
|
||
font-weight: 500;
|
||
text-align: center;
|
||
line-height: 1.2;
|
||
}
|
||
}
|
||
}
|
||
|
||
.payment-methods {
|
||
display: flex;
|
||
gap: 16rpx;
|
||
margin-bottom: 30rpx;
|
||
position: relative;
|
||
z-index: 1;
|
||
|
||
.payment-method {
|
||
flex: 1;
|
||
height: 88rpx;
|
||
background-color: #E8E8E8;
|
||
border-radius: 12rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 0 12rpx;
|
||
|
||
&.active {
|
||
background: linear-gradient(135deg, #4ECDC4 0%, #44A08D 100%);
|
||
|
||
.method-text {
|
||
color: #FFFFFF;
|
||
}
|
||
}
|
||
|
||
.method-text {
|
||
font-size: 28rpx;
|
||
color: #666666;
|
||
font-weight: 500;
|
||
text-align: center;
|
||
line-height: 1.2;
|
||
}
|
||
}
|
||
}
|
||
|
||
.upload-area {
|
||
width: 200rpx;
|
||
height: 200rpx;
|
||
border: 2rpx dashed #CCCCCC;
|
||
border-radius: 12rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin: 0 auto 40rpx;
|
||
background-color: #FFFFFF;
|
||
position: relative;
|
||
z-index: 1;
|
||
|
||
.upload-icon {
|
||
font-size: 80rpx;
|
||
color: #CCCCCC;
|
||
}
|
||
|
||
.uploaded-image {
|
||
width: 100%;
|
||
height: 100%;
|
||
border-radius: 12rpx;
|
||
}
|
||
}
|
||
|
||
.form-item {
|
||
margin-bottom: 20rpx;
|
||
position: relative;
|
||
z-index: 1;
|
||
|
||
.form-label {
|
||
font-size: 24rpx;
|
||
color: #666666;
|
||
display: block;
|
||
margin-bottom: 10rpx;
|
||
line-height: 1.5;
|
||
word-break: break-word;
|
||
}
|
||
|
||
.form-input {
|
||
width: 100%;
|
||
height: 80rpx;
|
||
background-color: #FFFFFF;
|
||
border: 1rpx solid #E5E5E5;
|
||
border-radius: 12rpx;
|
||
padding: 0 20rpx;
|
||
font-size: 26rpx;
|
||
box-sizing: border-box;
|
||
}
|
||
}
|
||
|
||
.apply-btn {
|
||
background: linear-gradient(135deg, #FF3B4E 0%, #FF6B7A 100%);
|
||
height: 88rpx;
|
||
border-radius: 44rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
position: relative;
|
||
z-index: 1;
|
||
margin-top: 20rpx;
|
||
|
||
.apply-btn-text {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #FFFFFF;
|
||
text-align: center;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style> |