diff --git a/src/api/pmset.ts b/src/api/pmset.ts index ef7aea6..ce2460f 100644 --- a/src/api/pmset.ts +++ b/src/api/pmset.ts @@ -174,3 +174,28 @@ export function amountToUsdcDisplay(raw: number | undefined): string { if (raw == null || !Number.isFinite(raw)) return '0.00' return (raw / USDC_SCALE).toFixed(2) } + +/** 提现配置(GET /pmset/getWithdrawConfig) */ +export interface WithdrawConfig { + /** 手续费,最小精度整数(1U=1e6;系统参数配置口径为 1=1U) */ + fee: number + /** 最低提现金额,最小精度整数(1U=1e6;系统参数配置口径为 1=1U) */ + minWithdrawAmount: number +} + +export interface WithdrawConfigResponse extends ApiResponse { + code: number + data?: WithdrawConfig + msg: string +} + +/** + * GET /pmset/getWithdrawConfig + * 获取提现手续费与最低提现金额(系统参数 withdrawFee / minWithdrawAmount,配置 1=1U;缺失自动插入) + */ +export async function getWithdrawConfig( + config?: { headers?: Record }, +): Promise { + return get('/pmset/getWithdrawConfig', undefined, config) +} + diff --git a/src/components/WithdrawDialog.vue b/src/components/WithdrawDialog.vue index 170bfec..92fff85 100644 --- a/src/components/WithdrawDialog.vue +++ b/src/components/WithdrawDialog.vue @@ -34,6 +34,21 @@ +
+
+ {{ t('withdraw.minAmount') }} + ${{ minAmountDisplay }} +
+
+ {{ t('withdraw.fee') }} + ${{ feeDisplay }} +
+
+ {{ t('withdraw.receiveAmount') }} + ${{ receiveAmountDisplay }} +
+
+ parseFloat(props.balance) || 0) const amountNum = computed(() => parseFloat(amount.value) || 0) +const feeDisplayNum = computed(() => feeRaw.value / 1_000_000) +const minAmountDisplayNum = computed(() => minWithdrawRaw.value / 1_000_000) +const feeDisplay = computed(() => amountToUsdcDisplay(feeRaw.value)) +const minAmountDisplay = computed(() => amountToUsdcDisplay(minWithdrawRaw.value)) +const receiveAmountDisplay = computed(() => { + const receive = Math.max(0, amountNum.value - feeDisplayNum.value) + return receive.toFixed(2) +}) const amountError = computed(() => { if (!amount.value) return '' if (amountNum.value <= 0) return t('withdraw.amountMustBePositive') if (amountNum.value > balanceNum.value) return t('withdraw.insufficientBalance') + if (minAmountDisplayNum.value > 0 && amountNum.value < minAmountDisplayNum.value) { + return t('withdraw.belowMinAmount', { min: minAmountDisplay.value }) + } + if (feeDisplayNum.value > 0 && amountNum.value <= feeDisplayNum.value) { + return t('withdraw.amountMustExceedFee', { fee: feeDisplay.value }) + } return '' }) @@ -145,7 +182,8 @@ const canSubmit = computed( amountNum.value <= balanceNum.value && hasValidDestination.value && !amountError.value && - !errorMessage.value, + !errorMessage.value && + !configLoading.value, ) function shortAddress(addr: string) { @@ -175,6 +213,23 @@ function resolveUserLoginWalletAddress(): string | undefined { return undefined } +async function loadWithdrawConfig() { + configLoading.value = true + try { + const res = await getWithdrawConfig() + if (res.code === 0 || res.code === 200) { + feeRaw.value = Number(res.data?.fee ?? 0) || 0 + minWithdrawRaw.value = Number(res.data?.minWithdrawAmount ?? 0) || 0 + } + } catch (e) { + console.error('[loadWithdrawConfig]', e) + feeRaw.value = 0 + minWithdrawRaw.value = 0 + } finally { + configLoading.value = false + } +} + /** 打开弹窗时自动连接浏览器钱包,且必须与登录账户地址一致 */ async function autoConnectWallet() { connectedAddress.value = '' @@ -299,7 +354,7 @@ watch( errorMessage.value = '' return } - await autoConnectWallet() + await Promise.all([loadWithdrawConfig(), autoConnectWallet()]) }, ) @@ -358,13 +413,35 @@ watch( } .amount-field { - margin-bottom: 16px; + margin-bottom: 10px; } .max-btn { text-transform: none; font-size: 0.8rem; } +.withdraw-meta { + display: flex; + flex-direction: column; + gap: 6px; + margin-bottom: 16px; + padding: 10px 12px; + background: #f9fafb; + border-radius: 8px; + font-size: 0.8125rem; + color: #6b7280; +} +.withdraw-meta-row { + display: flex; + justify-content: space-between; + align-items: center; + gap: 12px; +} +.withdraw-meta-row--receive { + color: #111827; + font-weight: 600; +} + .network-select { margin-bottom: 20px; } diff --git a/src/locales/en.json b/src/locales/en.json index 21f9fe5..9e654d6 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -519,7 +519,12 @@ "customAddressNotSupported": "Custom address is not supported for this withdrawal.", "loginWalletLabel": "Your login wallet", "connectingWallet": "Connecting wallet…", - "walletMismatch": "Switch your browser wallet to the same account you used to sign in." + "walletMismatch": "Switch your browser wallet to the same account you used to sign in.", + "fee": "Fee", + "minAmount": "Minimum withdrawal", + "receiveAmount": "You will receive", + "belowMinAmount": "Amount must be at least {min} USDC", + "amountMustExceedFee": "Amount must be greater than the fee of {fee} USDC" }, "earnActivity": { "title": "Participate to Earn", @@ -543,4 +548,4 @@ "ja": "日本語", "ko": "한국어" } -} \ No newline at end of file +} diff --git a/src/locales/ja.json b/src/locales/ja.json index 30620ec..39facc2 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -519,7 +519,12 @@ "customAddressNotSupported": "この出金ではカスタムアドレスはサポートされていません。", "loginWalletLabel": "ログイン中のウォレット", "connectingWallet": "ウォレットに接続しています…", - "walletMismatch": "ログイン時に使用したアカウントにブラウザのウォレットを切り替えてください。" + "walletMismatch": "ログイン時に使用したアカウントにブラウザのウォレットを切り替えてください。", + "fee": "手数料", + "minAmount": "最低出金額", + "receiveAmount": "受取金額", + "belowMinAmount": "出金額は {min} USDC 以上である必要があります", + "amountMustExceedFee": "出金額は手数料 {fee} USDC より大きい必要があります" }, "earnActivity": { "title": "キャンペーンに参加して稼ぐ", @@ -543,4 +548,4 @@ "ja": "日本語", "ko": "한국어" } -} \ No newline at end of file +} diff --git a/src/locales/ko.json b/src/locales/ko.json index 5d633f7..75dd607 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -519,7 +519,12 @@ "customAddressNotSupported": "이 출금에서는 사용자 지정 주소가 지원되지 않습니다.", "loginWalletLabel": "로그인 지갑", "connectingWallet": "지갑 연결 중…", - "walletMismatch": "로그인에 사용한 계정과 동일한 계정으로 브라우저 지갑을 전환해 주세요." + "walletMismatch": "로그인에 사용한 계정과 동일한 계정으로 브라우저 지갑을 전환해 주세요.", + "fee": "수수료", + "minAmount": "최소 출금 금액", + "receiveAmount": "실수령액", + "belowMinAmount": "출금 금액은 최소 {min} USDC 이상이어야 합니다", + "amountMustExceedFee": "출금 금액은 수수료 {fee} USDC 보다 커야 합니다" }, "earnActivity": { "title": "이벤트 참여하여 돈 벌기", @@ -543,4 +548,4 @@ "ja": "日本語", "ko": "한국어" } -} \ No newline at end of file +} diff --git a/src/locales/zh-CN.json b/src/locales/zh-CN.json index ac60a8a..f871dee 100644 --- a/src/locales/zh-CN.json +++ b/src/locales/zh-CN.json @@ -532,7 +532,12 @@ "customAddressNotSupported": "暂不支持自定义地址提现。", "loginWalletLabel": "登录钱包(提现地址)", "connectingWallet": "正在连接钱包…", - "walletMismatch": "请在浏览器钱包中切换到您登录时使用的账户。" + "walletMismatch": "请在浏览器钱包中切换到您登录时使用的账户。", + "fee": "手续费", + "minAmount": "最低提现金额", + "receiveAmount": "实际到账", + "belowMinAmount": "提现金额不能低于 {min} USDC", + "amountMustExceedFee": "提现金额必须大于手续费 {fee} USDC" }, "earnActivity": { "title": "参与活动赚钱", @@ -556,4 +561,4 @@ "ja": "日本語", "ko": "한국어" } -} \ No newline at end of file +} diff --git a/src/locales/zh-TW.json b/src/locales/zh-TW.json index 27d13cf..8a76d5e 100644 --- a/src/locales/zh-TW.json +++ b/src/locales/zh-TW.json @@ -519,7 +519,12 @@ "customAddressNotSupported": "暫不支援自訂地址提現。", "loginWalletLabel": "登入錢包(提現地址)", "connectingWallet": "正在連接錢包…", - "walletMismatch": "請在瀏覽器錢包中切換至您登入時使用的帳戶。" + "walletMismatch": "請在瀏覽器錢包中切換至您登入時使用的帳戶。", + "fee": "手續費", + "minAmount": "最低提現金額", + "receiveAmount": "實際到帳", + "belowMinAmount": "提現金額不能低於 {min} USDC", + "amountMustExceedFee": "提現金額必須大於手續費 {fee} USDC" }, "earnActivity": { "title": "參與活動賺錢",