feat(BD可操作的收益): 对接提现接口

This commit is contained in:
hzj 2025-10-30 20:41:06 +08:00
parent 0623bbc316
commit 4ee7b18476
2 changed files with 179 additions and 128 deletions

View File

@ -59,3 +59,50 @@ export const cancelInvite = async (userId) => {
throw error throw error
} }
} }
// 查询BD成员账单列表
export const getBdMemberBillList = async (type) => {
try {
const response = await get(`/team/bd/member-bill/list?type=${type}`)
return response
} catch (error) {
console.error('Failed to fetch BD member bill list:', error)
console.error('error:' + error.response.errorMsg)
throw error
}
}
// 查询BD成员账单明细
export const getBdMemberBillDetailList = async (teamId) => {
try {
const response = await get(`/team/bd/member-bill/detail-list`, { teamId })
return response
} catch (error) {
console.error('Failed to fetch BD member bill detail list:', error)
console.error('error:' + error.response.errorMsg)
throw error
}
}
// 查询BD团队月度收入汇总
export const getBdMonthlyIncome = async (bdUserId) => {
try {
const response = await get(`/team/bd/monthly-income`, { bdUserId })
return response
} catch (error) {
console.error('Failed to fetch BD monthly income:', error)
console.error('error:' + error.response.errorMsg)
throw error
}
}
// 提交提现申请
export const withdrawApply = async (data) => {
try {
const response = await post('/team/bd/withdraw/apply', data)
return response
} catch (error) {
console.error('Failed to fetch withdraw apply:', error)
throw error
}
}

View File

@ -29,9 +29,9 @@
" "
> >
<span v-if="loading" class="loading-text">Loading...</span> <span v-if="loading" class="loading-text">Loading...</span>
<span v-else style="font-weight: 700; color: #333; font-size: 1.1em">{{ <span v-else style="font-weight: 700; color: #333; font-size: 1.1em"
availableIncome >${{ availableIncome }}</span
}}</span> >
</div> </div>
</div> </div>
@ -67,7 +67,75 @@
</button> </button>
</div> </div>
<!-- 转账对象 --> <!-- Exchange -->
<div v-if="activeAction === 'Exchange'">
<div
style="
background-color: white;
padding: 16px;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
margin-bottom: 20px;
"
>
<!-- 兑换金额选择 -->
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px">
<div
v-for="option in exchangeOptions"
:key="option.id"
@click="selectExchangeOption(option)"
:style="{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
border:
selectedExchangeOption === option.id ? '2px solid #8b5cf6' : '2px solid #e5e7eb',
borderRadius: '12px',
cursor: 'pointer',
transition: 'all 0.2s',
backgroundColor: selectedExchangeOption === option.id ? '#f3f4f6' : 'white',
aspectRatio: '1/1',
}"
>
<img src="../../assets/icon/coin.png" alt="" style="width: 40%" />
<div style="font-weight: 500; color: #373232">
<!-- {{ option.coins }} -->
</div>
<div style="font-weight: 500; color: #131111">${{ option.cash }}</div>
</div>
</div>
</div>
<!-- 兑换按钮 -->
<div style="display: flex; justify-content: center; margin-top: 10px">
<button
style="
width: 70%;
padding: 12px;
background: linear-gradient(135deg, #bb92ff 2.82%, #8b45ff 99.15%);
color: white;
border: none;
border-radius: 32px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
"
@click="handleExchange"
:disabled="!selectedExchangeOption"
:style="{
background: !selectedExchangeOption
? '#ccc'
: 'linear-gradient(135deg, #bb92ff 2.82%, #8b45ff 99.15%)',
opacity: !selectedExchangeOption ? 0.6 : 1,
}"
>
Exchange
</button>
</div>
</div>
<!-- Transfer转账对象 -->
<div v-if="activeAction === 'Transfer'"> <div v-if="activeAction === 'Transfer'">
<div style="font-weight: 600; margin-bottom: 10px">Transfer to others</div> <div style="font-weight: 600; margin-bottom: 10px">Transfer to others</div>
<div <div
@ -178,7 +246,7 @@
</div> </div>
</div> </div>
<!-- 转账部分 --> <!-- Transfer -->
<div v-if="activeAction === 'Transfer'"> <div v-if="activeAction === 'Transfer'">
<div <div
style=" style="
@ -209,7 +277,7 @@
> >
<img src="../../assets/icon/coin.png" alt="" style="width: 40%" /> <img src="../../assets/icon/coin.png" alt="" style="width: 40%" />
<div style="font-weight: 500; color: #373232"> <div style="font-weight: 500; color: #373232">
{{ coin.amount }} <!-- {{ coin.amount }} -->
</div> </div>
<div style="font-weight: 500; color: #131111">${{ coin.price }}</div> <div style="font-weight: 500; color: #131111">${{ coin.price }}</div>
</div> </div>
@ -245,77 +313,7 @@
</div> </div>
</div> </div>
<!-- Exchange 页面内容 --> <!-- Cash out -->
<div v-if="activeAction === 'Exchange'">
<div
style="
background-color: white;
padding: 16px;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
margin-bottom: 20px;
"
>
<!-- 兑换金额选择 -->
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px">
<div
v-for="option in exchangeOptions"
:key="option.id"
@click="selectExchangeOption(option)"
:style="{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
border:
selectedExchangeOption === option.id ? '2px solid #8b5cf6' : '2px solid #e5e7eb',
borderRadius: '12px',
cursor: 'pointer',
transition: 'all 0.2s',
backgroundColor: selectedExchangeOption === option.id ? '#f3f4f6' : 'white',
aspectRatio: '1/1',
}"
>
<img src="../../assets/icon/coin.png" alt="" style="width: 40%" />
<div style="font-weight: 500; color: #373232">
{{ option.coins }}
</div>
<div style="font-weight: 500; color: #131111">
{{ option.cash }}
</div>
</div>
</div>
</div>
<!-- 兑换按钮 -->
<div style="display: flex; justify-content: center; margin-top: 10px">
<button
style="
width: 70%;
padding: 12px;
background: linear-gradient(135deg, #bb92ff 2.82%, #8b45ff 99.15%);
color: white;
border: none;
border-radius: 32px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
"
@click="handleExchange"
:disabled="!selectedExchangeOption"
:style="{
background: !selectedExchangeOption
? '#ccc'
: 'linear-gradient(135deg, #bb92ff 2.82%, #8b45ff 99.15%)',
opacity: !selectedExchangeOption ? 0.6 : 1,
}"
>
Exchange
</button>
</div>
</div>
<!-- Cash out 页面内容 -->
<div v-if="activeAction === 'Cash out'"> <div v-if="activeAction === 'Cash out'">
<!-- 提现资料 --> <!-- 提现资料 -->
<!-- 银行帐号信息 --> <!-- 银行帐号信息 -->
@ -464,19 +462,25 @@
import { ref, reactive, onMounted, onUnmounted, computed } from 'vue' import { ref, reactive, onMounted, onUnmounted, computed } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import MobileHeader from '@/components/MobileHeader.vue' import MobileHeader from '@/components/MobileHeader.vue'
import { getBankBalance, userBankTransfer } from '@/api/wallet.js' import {
getBankBalance,
userBankTransfer,
userSalaryCheckExchange,
userBankExchangeGold,
} from '@/api/wallet.js'
import { getSelectedPayee, clearSelectedPayee } from '@/utils/payeeStore.js' import { getSelectedPayee, clearSelectedPayee } from '@/utils/payeeStore.js'
import { showError, showSuccess } from '@/utils/toast.js' import { showError, showSuccess } from '@/utils/toast.js'
import { setApplyInfo, getApplyInfo } from '@/utils/applyStore.js' import { setApplyInfo, getApplyInfo } from '@/utils/applyStore.js'
import maskLayer from '@/components/MaskLayer.vue' import maskLayer from '@/components/MaskLayer.vue'
import { withdrawApply } from '@/api/bdCenter.js'
import { getUserId } from '@/utils/userStore.js'
const router = useRouter() const router = useRouter()
const availableIncome = ref('$23456') const availableIncome = ref('')
const selectedCoin = ref(null) const selectedCoin = ref(null)
const selectedExchangeOption = ref(null) const selectedExchangeOption = ref(null)
const selectedCashOutOption = ref(null) const activeAction = ref('Exchange')
const activeAction = ref('Transfer')
const loading = ref(false) const loading = ref(false)
const maskLayerShow = ref(false) const maskLayerShow = ref(false)
@ -500,12 +504,6 @@ const CashOut = () => {
} }
} }
//
const Receive = () => {
setApplyInfo()
maskLayerShow.value = false
}
// //
const selectedPayee = reactive({ const selectedPayee = reactive({
id: null, id: null,
@ -530,12 +528,12 @@ const coinOptions = reactive([
// //
const exchangeOptions = reactive([ const exchangeOptions = reactive([
{ id: 1, coins: '10000', cash: '$1' }, { id: 1, coins: 10500, cash: 1 },
{ id: 2, coins: '10000', cash: '$1' }, { id: 2, coins: 52500, cash: 5 },
{ id: 3, coins: '10000', cash: '$1' }, { id: 3, coins: 105000, cash: 10 },
{ id: 4, coins: '10000', cash: '$1' }, { id: 4, coins: 525000, cash: 50 },
{ id: 5, coins: '10000', cash: '$1' }, { id: 5, coins: 1050000, cash: 100 },
{ id: 6, coins: '10000', cash: '$1' }, { id: 6, coins: 2100000, cash: 200 },
]) ])
const bankCardInfo = ref({}) const bankCardInfo = ref({})
@ -559,14 +557,14 @@ const fetchBankBalance = async () => {
const response = await getBankBalance() const response = await getBankBalance()
if (response.status && typeof response.body === 'number') { if (response.status && typeof response.body === 'number') {
availableIncome.value = `$${response.body.toFixed(2)}` availableIncome.value = response.body.toFixed(2) || '0.00'
} else { } else {
availableIncome.value = '$0.00' availableIncome.value = '-'
} }
} catch (error) { } catch (error) {
console.error('Failed to fetch bank balance:', error) console.error('Failed to fetch bank balance:', error)
availableIncome.value = '$0.00' availableIncome.value = '-'
showError('Failed to load balance. Please try again.') showError(error.response.errorMsg)
} finally { } finally {
loading.value = false loading.value = false
} }
@ -587,7 +585,6 @@ const handleAction = (actionName) => {
// //
selectedCoin.value = null selectedCoin.value = null
selectedExchangeOption.value = null selectedExchangeOption.value = null
selectedCashOutOption.value = null
} }
// //
@ -621,14 +618,6 @@ const selectExchangeOption = (option) => {
} }
} }
const selectCashOutOption = (option) => {
if (selectedCashOutOption.value === option.id) {
selectedCashOutOption.value = null
} else {
selectedCashOutOption.value = option.id
}
}
const transfer = async () => { const transfer = async () => {
if (!selectedCoin.value) { if (!selectedCoin.value) {
showError('Please select an amount first') showError('Please select an amount first')
@ -652,25 +641,18 @@ const transfer = async () => {
const response = await userBankTransfer(transferData) const response = await userBankTransfer(transferData)
if (response.status) { if (response.status) {
showSuccess(`Successfully transferred $${selectedCoinData.price} to ${selectedPayee.name}`) showSuccess(`Successfully transferred $${selectedCoinData.price} to ${selectedPayee.name}`)
selectedCoin.value = null
await fetchBankBalance()
} else { } else {
showError(`Failed to transfer $${selectedCoinData.price}`) showError(`Failed to transfer $${selectedCoinData.price}`)
} }
selectedCoin.value = null
await fetchBankBalance()
} catch (error) { } catch (error) {
console.error('Transfer failed:', error) console.error('Transfer failed:', error)
if (error.errorCode === 5000) { showError(error.response.errorMsg)
showError('Insufficient balance')
} else if (error.errorCode === 5010 || error.errorCode === 5009) {
showError('Payment password error')
} else {
showError('Transfer failed, please try again later')
}
} }
} }
const handleExchange = () => { const handleExchange = async () => {
if (!selectedExchangeOption.value) { if (!selectedExchangeOption.value) {
showError('Please select an amount first') showError('Please select an amount first')
return return
@ -679,19 +661,41 @@ const handleExchange = () => {
const selectedOption = exchangeOptions.find( const selectedOption = exchangeOptions.find(
(option) => option.id === selectedExchangeOption.value (option) => option.id === selectedExchangeOption.value
) )
showSuccess(`Exchanging ${selectedOption.coins} coins for ${selectedOption.cash}`)
selectedExchangeOption.value = null try {
//
const response = await userBankExchangeGold({
coinId: selectedOption.id,
amount: selectedOption.cash,
price: selectedOption.cash,
})
if (response.status === true || response.errorCode === 0) {
showSuccess(`Successfully exchanged`)
//
await fetchBankBalance()
}
selectedExchangeOption.value = null
} catch (error) {
console.error('Exchange failed:', error)
showError(error.response.errorMsg)
}
} }
const handleCashOut = () => { //
if (!selectedCashOutOption.value) { const Receive = async () => {
showError('Please select an amount first') try {
return const resApply = await withdrawApply({ ...getApplyInfo(), activityId: getUserId() })
if (resApply.status) {
setApplyInfo()
}
maskLayerShow.value = false
} catch (error) {
maskLayerShow.value = false
showError(error.response.errorMsg)
} }
const selectedOption = cashOutOptions.find((option) => option.id === selectedCashOutOption.value)
showSuccess(`Cashing out ${selectedOption.coins} coins for ${selectedOption.cash}`)
selectedCashOutOption.value = null
} }
// //
@ -706,7 +710,7 @@ onMounted(() => {
onUnmounted(() => { onUnmounted(() => {
clearPayee() clearPayee()
setApplyInfo() // setApplyInfo()
}) })
</script> </script>