diff --git a/src/api/bdCenter.js b/src/api/bdCenter.js index 5371fdf..a09f59a 100644 --- a/src/api/bdCenter.js +++ b/src/api/bdCenter.js @@ -60,17 +60,6 @@ export const cancelInvite = async (userId) => { } } -// 提交提现申请 -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 - } -} - // 查询BD/BDLearer 成员账单列表 export const getBdMemberBillList = async (type) => { try { diff --git a/src/api/wallet.js b/src/api/wallet.js index 0e95e8d..bf991ec 100644 --- a/src/api/wallet.js +++ b/src/api/wallet.js @@ -323,3 +323,14 @@ export const updateWithdrawInfo = async (data) => { throw error } } + +// 提交提现申请 +export const withdrawApply = async (data) => { + try { + const response = await post('/wallet/bank/withdraw', data) + return response + } catch (error) { + console.error('Failed to fetch withdraw apply:', error) + throw error + } +} diff --git a/src/assets/icon/addWhite.png b/src/assets/icon/addWhite.png new file mode 100644 index 0000000..6141d92 Binary files /dev/null and b/src/assets/icon/addWhite.png differ diff --git a/src/router/index.js b/src/router/index.js index 4357578..6c7ac0e 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -317,6 +317,12 @@ const router = createRouter({ component: () => import('../views/Activities/heroesDay/index.vue'), meta: { requiresAuth: true }, }, + { + path: '/bank-card', + name: 'bank-card', + component: () => import('../views/Wallet/CashOut/BankCard.vue'), + meta: { requiresAuth: true }, + }, ], }) diff --git a/src/utils/pageConfig.js b/src/utils/pageConfig.js index c1108d8..67d56e0 100644 --- a/src/utils/pageConfig.js +++ b/src/utils/pageConfig.js @@ -8,39 +8,47 @@ export const PageConfig = { needsBankBalance: true, needsWorkStatistics: true, needsRouteGuard: true, - title: "Host Center", - userTag: "👑 Host", + title: 'Host Center', + userTag: '👑 Host', }, COIN_SELLER: { needsBankBalance: true, needsWorkStatistics: false, // Coin Seller 不需要工作统计 needsRouteGuard: true, - title: "Coin Seller", - userTag: "💰 Coin Seller", + title: 'Coin Seller', + userTag: '💰 Coin Seller', }, AGENCY_CENTER: { needsBankBalance: true, needsWorkStatistics: true, needsRouteGuard: true, - title: "Agency Center", - userTag: "🏢 Agency", + title: 'Agency Center', + userTag: '🏢 Agency', + }, + + BD_LEADER_CENTER: { + needsBankBalance: true, + needsWorkStatistics: false, // BD 可能不需要日常工作统计 + needsRouteGuard: true, + title: 'BD Leader Center', + userTag: '📈 BD Leader', }, BD_CENTER: { needsBankBalance: true, needsWorkStatistics: false, // BD 可能不需要日常工作统计 needsRouteGuard: true, - title: "BD Center", - userTag: "📈 BD", + title: 'BD Center', + userTag: '📈 BD', }, APPLY: { needsBankBalance: false, // 申请页面不需要余额 needsWorkStatistics: false, // 申请页面不需要工作统计 needsRouteGuard: false, // 申请页面不需要身份检查 - title: "Apply", + title: 'Apply', userTag: null, // 申请页面可能没有身份标签 }, @@ -48,10 +56,10 @@ export const PageConfig = { needsBankBalance: false, needsWorkStatistics: false, // ADMIN 可能不需要日常工作统计 needsRouteGuard: true, - title: "ADMIN Center", - userTag: "ADMIN", + title: 'ADMIN Center', + userTag: 'ADMIN', }, -}; +} /** * 获取页面配置的工具函数 @@ -59,16 +67,16 @@ export const PageConfig = { * @returns {Object} 页面配置对象 */ export function getPageConfig(pageType) { - const config = PageConfig[pageType]; + const config = PageConfig[pageType] if (!config) { - console.warn(`未找到页面配置: ${pageType}`); - return PageConfig.HOST_CENTER; // 默认使用 HOST_CENTER 配置 + console.warn(`未找到页面配置: ${pageType}`) + return PageConfig.HOST_CENTER // 默认使用 HOST_CENTER 配置 } - return config; + return config } // ========================================== -import { usePageInitialization } from "./usePageInitialization.js"; +import { usePageInitialization } from './usePageInitialization.js' /** * 使用预配置的页面初始化函数 @@ -77,13 +85,13 @@ import { usePageInitialization } from "./usePageInitialization.js"; * @returns {Object} usePageInitialization 的返回值 */ export function usePageInitializationWithConfig(pageType, customOptions = {}) { - const pageConfig = getPageConfig(pageType); + const pageConfig = getPageConfig(pageType) // 合并默认配置和自定义选项 const options = { ...pageConfig, ...customOptions, - }; + } - return usePageInitialization(options); + return usePageInitialization(options) } diff --git a/src/utils/permissionManager.js b/src/utils/permissionManager.js index bc8b650..4a1cde9 100644 --- a/src/utils/permissionManager.js +++ b/src/utils/permissionManager.js @@ -143,6 +143,7 @@ export const ROLE_PERMISSIONS = { '/cash-out', // 提现页面 '/cash-out-details', //提现详情页面 '/KYC', //提现资料提交 + '/bank-card', //选择银行卡 ], // 加载页面 diff --git a/src/utils/routeGuard.js b/src/utils/routeGuard.js index 10e4ea0..8c349eb 100644 --- a/src/utils/routeGuard.js +++ b/src/utils/routeGuard.js @@ -422,6 +422,7 @@ class RouteGuard { '/cash-out', // 提现页面 '/cash-out-details', //提现详情页面 '/KYC', //提现资料提交 + '/bank-card', //选择银行卡 ] return publicPages.includes(path) } diff --git a/src/views/BDCenter/availableIncome.vue b/src/views/BDCenter/availableIncome.vue index 7e724e7..daaed5f 100644 --- a/src/views/BDCenter/availableIncome.vue +++ b/src/views/BDCenter/availableIncome.vue @@ -40,7 +40,7 @@ - +
- - +
-
+
{{ t('kyc') }}
+ + +
:
+ +
+ Review passed +
+ + +
+ Review failed +
+ + +
+ Awaiting review +
- + +
- +
@@ -347,12 +394,12 @@
- +
{{ - t('passport_id_card', { current: bankCardInfo.cardImages.length }) + t('passport_id_card', { current: bankCardInfo.previewUrls.length }) }}
@@ -360,7 +407,7 @@
@@ -374,13 +421,13 @@
{{ t('other_description') }}:
- {{ bankCardInfo.description }} + {{ bankCardInfo.otherDescription }}
- +
@@ -406,9 +454,10 @@
- - + +
+
+
{{ t('tips') }}
+
+ Are you sure you want to exchangecoins? +
+
+
+ Cancel +
+
+ Confirm +
+
+
+
+ + +
+
+
{{ t('tips') }}
+
+ Please fill in the information carefully. You can only withdraw cash after the + information is completed. +
+
+ *lf there is a problem with the card number and the transfer cannot be made, it will + result in the review being. +
+
+ {{ t('receive') }} +
+
+
+ + +
+
+
+
Cash out
+
+ + +
+
+ Withdrawal Method: {{ usedBankCard?.cardType || '' }} +
+
+
Please select a bank card
+ +
+
+ + +
+ +
+ +
+ *The cash out amount must be >= $50 +
+ +
+
+ {{ t('cash_out') }} +
+
+
+
+ + +
{{ t('receive') }}
@@ -472,12 +737,13 @@ import { userBankTransfer, userSalaryCheckExchange, userBankExchangeGold, + getBankCardList, //获取正在使用的银行卡 + getWithdrawInfoList, //获取申请提现信息 + withdrawApply, //提现 } from '@/api/wallet.js' import { getSelectedPayee, clearSelectedPayee } from '@/utils/payeeStore.js' import { showError, showSuccess } from '@/utils/toast.js' -import { setApplyInfo, getApplyInfo } from '@/utils/applyStore.js' import maskLayer from '@/components/MaskLayer.vue' -import { withdrawApply } from '@/api/bdCenter.js' import { getUserId } from '@/utils/userStore.js' import { setDocumentDirection } from '@/locales/i18n' @@ -493,7 +759,25 @@ const selectedExchangeOption = ref(null) const activeAction = ref('Exchange') const loading = ref(false) -const maskLayerShow = ref(false) +const exchangeTipShow = ref(false) +const cashOutTipShow = ref(false) +const cashOutTypeShow = ref(false) +const cashOutShow = ref(false) + +const cashOutAmount = ref(null) + +const maskLayerShow = computed(() => { + return exchangeTipShow.value || cashOutTipShow.value || cashOutShow.value || cashOutTypeShow.value +}) + +const usedBankCard = ref(null) //正在使用的银行卡 + +const closedPopup = () => { + exchangeTipShow.value = false + cashOutTipShow.value = false + cashOutShow.value = false + cashOutTypeShow.value = false +} // 操作按钮 const actions = ref([ @@ -502,19 +786,10 @@ const actions = ref([ { name: 'Cash out', lang: 'cash_out' }, ]) -// 查看历史提现信息 -const gotoKYC = () => { - router.push('/KYC') -} - // 提现按钮 const CashOut = () => { - if (hasBankCard.value) { - try { - maskLayerShow.value = true - } catch (error) { - showError(error.errorMsg) - } + if (hasKYC.value && bankCardInfo.value?.status === 'PASS') { + cashOutTypeShow.value = true } } @@ -550,11 +825,45 @@ const exchangeOptions = reactive([ { id: 6, coins: 2100000, cash: 200 }, ]) -const bankCardInfo = ref({}) -const hasBankCard = computed(() => { - return Object.keys(bankCardInfo.value).length > 0 +const bankCardInfo = ref(null) +const hasKYC = computed(() => { + return bankCardInfo.value != null }) +// 获取提现信息列表 +const getWithdrawInfoListData = async () => { + try { + const resWithdrawInfoList = await getWithdrawInfoList() + console.log('提现信息列表:', resWithdrawInfoList) + if (resWithdrawInfoList.status && resWithdrawInfoList.body?.length > 0) { + let imgList = JSON.parse(resWithdrawInfoList.body[0].passportFrontUrl) + let previewUrls = imgList.map((item) => item) + bankCardInfo.value = { previewUrls, ...resWithdrawInfoList.body[0] } + } + } catch (error) { + console.error('获取提现信息列表失败:', error) + showError(error.response?.errorMsg) + } +} + +// 获取银行卡列表 +const getBankCards = async () => { + try { + const resBankCards = await getBankCardList() + console.log('银行卡列表:', resBankCards) + if (resBankCards.status && resBankCards.body) { + // 处理银行卡列表数据 + resBankCards.body.forEach((card) => { + if (card.use) { + usedBankCard.value = card + } + }) + } + } catch (error) { + console.error('获取银行卡列表失败:', error) + } +} + // 初始化收款人信息 const initializePayee = () => { const savedPayee = getSelectedPayee() @@ -584,11 +893,22 @@ const fetchBankBalance = async () => { } } -// 方法 +// 前往提交个人资料 +const gotoKYC = () => { + router.push('/KYC') +} + +// 前往选择提交方式 +const gotoselectBank = () => { + router.push('/bank-card') +} + +// 跳转详情 const showDetails = () => { router.push('/income-details') } +// 跳转搜索收款人 const searchPayee = () => { router.push('/search-payee') } @@ -616,6 +936,7 @@ const clearPayee = () => { clearSelectedPayee() } +// 选择转账金币 const selectCoin = (coin) => { if (selectedCoin.value === coin.id) { selectedCoin.value = null @@ -624,6 +945,7 @@ const selectCoin = (coin) => { } } +// 选择兑换金币 const selectExchangeOption = (option) => { if (selectedExchangeOption.value === option.id) { selectedExchangeOption.value = null @@ -632,6 +954,7 @@ const selectExchangeOption = (option) => { } } +// 转账操作 const transfer = async () => { if (!selectedCoin.value) { showError(t('please_select_amount')) @@ -668,6 +991,7 @@ const transfer = async () => { } } +// 兑换操作 const handleExchange = async () => { if (!selectedExchangeOption.value) { showError(t('please_select_coin_amount')) @@ -700,33 +1024,39 @@ const handleExchange = async () => { } } +// 是否可以提现 +const checkStatus = computed(() => { + return bankCardInfo.value?.status == 'PASS' && usedBankCard.value?.id && cashOutAmount.value > 50 +}) + // 确认提现 const Receive = async () => { - try { - const resApply = await withdrawApply({ ...getApplyInfo(), activityId: getUserId() }) - if (resApply.status) { - setApplyInfo() + if (checkStatus.value) { + try { + const resApply = await withdrawApply({ + amount: cashOutAmount.value, + acceptBankCardId: usedBankCard.value.id, + }) + if (resApply.status) { + cashOutShow.value = true + } + } catch (error) { + cashOutShow.value = false + showError(error.response?.errorMsg || t('something_went_wrong')) } - maskLayerShow.value = false - } catch (error) { - maskLayerShow.value = false - showError(error.response?.errorMsg || t('something_went_wrong')) } } // 页面加载时获取银行余额和初始化收款人 onMounted(() => { - fetchBankBalance() - initializePayee() - if (getApplyInfo()) { - bankCardInfo.value = - { ...getApplyInfo(), cardImages: JSON.parse(getApplyInfo().cardImages) } || {} - } + fetchBankBalance() // 获取银行余额 + initializePayee() // 初始化收款人信息 + getWithdrawInfoListData() // 获取提现信息列表 + getBankCards() // 获取正在使用的银行卡 }) onUnmounted(() => { clearPayee() - // setApplyInfo() }) @@ -736,6 +1066,11 @@ onUnmounted(() => { font-family: 'SF Pro Text'; } +input::placeholder { + font-weight: 510; + color: rgba(0, 0, 0, 0.4); +} + .transfer { font-family: -apple-system, BlinkMacSystemFont, sans-serif; width: 100vw; diff --git a/src/views/Wallet/CashOut/BankCard.vue b/src/views/Wallet/CashOut/BankCard.vue new file mode 100644 index 0000000..4355c15 --- /dev/null +++ b/src/views/Wallet/CashOut/BankCard.vue @@ -0,0 +1,536 @@ + + + + + diff --git a/src/views/Wallet/CashOut/KYC.vue b/src/views/Wallet/CashOut/KYC.vue index 0ce934d..c6392f5 100644 --- a/src/views/Wallet/CashOut/KYC.vue +++ b/src/views/Wallet/CashOut/KYC.vue @@ -15,7 +15,7 @@ > @@ -33,11 +33,10 @@ " >
+ +
+
Current status:
+
+ Review passed +
+
+ Review failed +
+
+ Awaiting review +
+
+
description.value.length) +const count = computed(() => applyInfo.value.otherDescription.length) //字数 -const previewUrls = ref([]) //预览图 -const tempFiles = ref([]) //用于提交图片的临时文件列表 -const resImgUrls = ref([]) //用于提交申请的文件数组 +const tempFiles = ref([]) //用于提交的临时图片文件列表 +const previewUrls = ref([]) //预览图片数组 +const resImgUrls = ref([]) //用于提交申请的图片数组 -// 更新字符计数 -const updateCount = () => { - // 这个函数在模板中已经通过 @input 调用 -} +const updateStatus = ref(false) //是否为修改 -// 点击上传图片 -// 处理文件选择 +const applyInfo = ref({ + id: '', //提现信息ID + contactNumber: '', //银行卡号 + category: 'CARD', //类别 + otherDescription: '', //其他描述 + passportFrontUrl: '', //图片 + passportBackUrl: 'meaningless', +}) + +// 是否全填 +const checkStatus = computed(() => { + return applyInfo.value.contactNumber != '' && previewUrls.value.length > 0 +}) + +// 处理文件选择(每次选一张) const handleFileChange = (e) => { - //最多3张图片 + // 最多3张图片 if (previewUrls.value.length < 3) { const fileList = e.target.files // 获取第一个文件对象 - // 1. 检查是否有文件 + // 检查是否有文件 if (!fileList || fileList.length === 0) { console.error('未选择文件') return } - // 2. 提取第一个文件并验证 + // 提取第一个文件并验证 const file = fileList[0] if (!file.type || !file.type.startsWith('image/')) { console.error(`不支持的文件类型: ${file.type || '未知'}`) @@ -179,7 +230,6 @@ const handleFileChange = (e) => { previewUrls.value.push(URL.createObjectURL(file)) //临时文件列表,用于上传 tempFiles.value.push(file) - // uploadImgUrl() } else { showWarning(t('max_images_warning')) } @@ -208,22 +258,75 @@ const uploadImgUrl = async () => { // 提交申请 const Submit = async () => { - if (!cardNum.value) { + // 检查是否漏填 + console.log('checkStatus.value:', checkStatus.value) + + if (checkStatus.value) { + await uploadImgUrl() + applyInfo.value.passportFrontUrl = JSON.stringify(resImgUrls.value) + if (updateStatus.value) { + console.log('更新信息:', applyInfo.value) + updateWithdrawInfoData() + } else { + console.log('添加信息:', applyInfo.value) + addWithdrawInfoData() + } + // router.go(-1) + } else { showError(t('please_enter_contact_number')) return } - - await uploadImgUrl() - let data = { - amount: 10, - contactNumber: cardNum.value, - description: description.value, - cardImages: JSON.stringify(resImgUrls.value), - } - setApplyInfo(data) - router.go(-1) - showSuccess(t('application_submitted')) } + +// 获取提现信息列表 +const getWithdrawInfoListData = async () => { + try { + const resWithdrawInfoList = await getWithdrawInfoList() + console.log('提现信息列表:', resWithdrawInfoList) + if (resWithdrawInfoList.status && resWithdrawInfoList.body?.length > 0) { + updateStatus.value = true + applyInfo.value = resWithdrawInfoList.body[0] + let imgList = JSON.parse(resWithdrawInfoList.body[0].passportFrontUrl) + previewUrls.value = imgList.map((item) => item) + resImgUrls.value = imgList.map((item) => item) + } + } catch (error) { + console.error('获取提现信息列表失败:', error) + showError(error.response?.errorMsg) + } +} + +// 添加提现信息 +const addWithdrawInfoData = async () => { + try { + const resAddWithdrawInfo = await addWithdrawInfo(applyInfo.value) + if (resAddWithdrawInfo.status) { + showSuccess(t('application_submitted')) + getWithdrawInfoListData() // 重新获取提现信息列表 + } + } catch (error) { + showError(error.response?.errorMsg) + throw error + } +} + +// 更新提现信息 +const updateWithdrawInfoData = async () => { + try { + const resUpdateWithdrawInfo = await updateWithdrawInfo(applyInfo.value) + if (resUpdateWithdrawInfo.status) { + showSuccess(t('application_submitted')) + getWithdrawInfoListData() // 重新获取提现信息列表 + } + } catch (error) { + showError(error.response?.errorMsg) + throw error + } +} + +onMounted(() => { + getWithdrawInfoListData() // 获取个人申请信息 +})