|
@@ -7,426 +7,429 @@
|
|
|
}
|
|
|
</route>
|
|
|
<template>
|
|
|
- <view class="w-full min-h-screen bg-bgc flex flex-col items-center text-white">
|
|
|
- <text class="mt-70rpx fw-540 text-[45rpx]">{{ $t('purse.Withdraw') }}</text>
|
|
|
- <!-- 余额显示 -->
|
|
|
- <view class="w-690rpx h-538rpx rounded-30rpx bg-[#27272A] flex items-center flex-col mt-45rpx">
|
|
|
- <!-- TON输入框 -->
|
|
|
- <view class="custom-input mt-30rpx">
|
|
|
- <image src="@/static/images/purse/u.png" class="w-70rpx h-70rpx ml-14rpx"></image>
|
|
|
- <input
|
|
|
- type="text"
|
|
|
- v-model="tonInput"
|
|
|
- @input="handleTonInput"
|
|
|
- placeholder="0"
|
|
|
- class="input-field"
|
|
|
- />
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 提示信息 -->
|
|
|
- <text
|
|
|
- class="text-26rpx text-left w-full mt-30rpx ml-56rpx"
|
|
|
- :class="{ 'text-red-500': showError }"
|
|
|
- >
|
|
|
- {{ errorMessage || i18n.global.t('purse.Minimum') }}
|
|
|
- </text>
|
|
|
-
|
|
|
- <!-- 金币输入框 -->
|
|
|
- <view class="custom-input mt-40rpx">
|
|
|
- <image src="@/static/images/purse/blackGB.png" class="w-70rpx h-70rpx ml-14rpx"></image>
|
|
|
- <input
|
|
|
- type="text"
|
|
|
- v-model="coinInput"
|
|
|
- @input="handleCoinInput"
|
|
|
- placeholder="Enter withdrawal address"
|
|
|
- class="input-field"
|
|
|
- />
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 连接钱包/提现按钮 -->
|
|
|
- <view
|
|
|
- @click="triggerConnect"
|
|
|
- class="w-630rpx h-100rpx rounded-20rpx btn-bg mt-60rpx flex items-center justify-center cursor-pointer"
|
|
|
- >
|
|
|
- <text class="text-32rpx text-white">{{ wallet ? 'Withdraw' : 'Connect' }}</text>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- <!-- 记录刷新区 -->
|
|
|
- <view class="w-690rpx mt-49rpx flex items-center justify-between">
|
|
|
- <text>{{ $t('purse.Record') }}</text>
|
|
|
- <image
|
|
|
- @click="refreshRecords"
|
|
|
- src="@/static/images/purse/shuaxin.png"
|
|
|
- class="w-42rpx h-42rpx"
|
|
|
- ></image>
|
|
|
- </view>
|
|
|
- <view
|
|
|
- v-for="(record, index) in pcamaignList"
|
|
|
- :key="index"
|
|
|
- class="w-690rpx h-130rpx mt-30rpx rounded-20rpx bg-[#13355A] flex items-center justify-between mt-20rpx"
|
|
|
- >
|
|
|
- <view class="flex items-center ml-20rpx justify-between w-full">
|
|
|
- <view>
|
|
|
- <image src="@/static/images/purse/blackGB.png" class="w-70rpx h-70rpx mr-29rpx" />
|
|
|
- <text class="text-24rpx text-white mr-20rpx">{{ record.pay_time }}</text>
|
|
|
- </view>
|
|
|
-
|
|
|
- <view class="flex items-center">
|
|
|
- <text class="text-24rpx text-white mr-40rpx">+{{ record.coin_exchange }}</text>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- <wd-notify />
|
|
|
+ <view>123</view>
|
|
|
</template>
|
|
|
-
|
|
|
-<script setup lang="ts">
|
|
|
-import {
|
|
|
- useTonWallet,
|
|
|
- useTonConnectUI,
|
|
|
- useTonConnectModal,
|
|
|
- useTonAddress,
|
|
|
-} from '@townsquarelabs/ui-vue'
|
|
|
-import { useTelegramBackButton } from '@/hooks/useTelegramBackButton'
|
|
|
-import {
|
|
|
- getCoinAddress,
|
|
|
- getRecharge,
|
|
|
- postRechargeCoin,
|
|
|
- postRechargeCoinReturn,
|
|
|
- RechargeCoinList,
|
|
|
-} from '@/service/purse'
|
|
|
-import i18n from '@/locale/index'
|
|
|
-import { useNotify } from 'wot-design-uni'
|
|
|
-
|
|
|
-const { showNotify } = useNotify()
|
|
|
-const { open, close } = useTonConnectModal()
|
|
|
-const { isVisible } = useTelegramBackButton(() => {
|
|
|
- uni.navigateBack()
|
|
|
-})
|
|
|
-const userFriendlyAddress = useTonAddress()
|
|
|
-// 状态管理
|
|
|
-const wallet = useTonWallet()
|
|
|
-const { tonConnectUI } = useTonConnectUI()
|
|
|
-const tonInput = ref('') // TON 输入值
|
|
|
-const coinInput = ref('') // 金币输入值
|
|
|
-const userBalance = ref(0)
|
|
|
-const errorMessage = ref('')
|
|
|
-const showError = ref(false)
|
|
|
-const inputMode = ref('ton') // 当前输入模式: 'ton' | 'coin'
|
|
|
-
|
|
|
-// 计算最小提现金额(以nanoTON为单位)
|
|
|
-const MIN_WITHDRAWAL = 0.1 // 1 TON
|
|
|
-
|
|
|
-let balanceInterval: number | null = null
|
|
|
-
|
|
|
-// 获取钱包余额
|
|
|
-const getWalletBalance = async (address: string) => {
|
|
|
- try {
|
|
|
- const response = await fetch(
|
|
|
- `https://toncenter.com/api/v2/getAddressBalance?address=${address}`,
|
|
|
- )
|
|
|
- const data = await response.json()
|
|
|
-
|
|
|
- if (data.ok) {
|
|
|
- userBalance.value = Number(data.result) / 1000000000
|
|
|
- console.log('Wallet balance:', userBalance.value, 'TON')
|
|
|
- } else {
|
|
|
- console.error('Failed to get balance, invalid response:', data)
|
|
|
- userBalance.value = 0
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- console.error('Failed to fetch balance:', error)
|
|
|
- userBalance.value = 0
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 获取兑换比例
|
|
|
-const proportion = ref(0)
|
|
|
-const getProportion = async () => {
|
|
|
- const { data } = await getRecharge()
|
|
|
- proportion.value = data.proportion
|
|
|
-}
|
|
|
-
|
|
|
-// 获取系统充值钱包地址
|
|
|
-const coinAddress = ref()
|
|
|
-const getCoinAddressFn = async () => {
|
|
|
- const { data } = await getCoinAddress()
|
|
|
- coinAddress.value = data.coin_address
|
|
|
-}
|
|
|
-
|
|
|
-const formatNumberInput = (value: string) => {
|
|
|
- // 移除非数字和小数点
|
|
|
- value = value.replace(/[^\d.]/g, '')
|
|
|
-
|
|
|
- // 处理前导零
|
|
|
- if (value.startsWith('0') && value.length > 1 && !value.startsWith('0.')) {
|
|
|
- value = value.replace(/^0+/, '')
|
|
|
- }
|
|
|
-
|
|
|
- // 如果是第一次输入小数点且在开头,自动补0
|
|
|
- if (value.startsWith('.')) {
|
|
|
- value = '0' + value
|
|
|
- }
|
|
|
-
|
|
|
- // 限制只能有一个小数点
|
|
|
- if (value.includes('.') && value.split('.').length > 2) {
|
|
|
- return value.substring(0, value.lastIndexOf('.'))
|
|
|
- }
|
|
|
-
|
|
|
- // 限制小数位数为6位
|
|
|
- if (value.includes('.')) {
|
|
|
- const [integer, decimal] = value.split('.')
|
|
|
- return `${integer}.${decimal.slice(0, 6)}`
|
|
|
- }
|
|
|
-
|
|
|
- return value
|
|
|
-}
|
|
|
-// 常量定义
|
|
|
-const MIN_TON = 0.1 // 最小兑换数量改为 0.1 TON
|
|
|
-const MAX_TON = 1000000 // 最大 TON 输入限制
|
|
|
-const MAX_DECIMALS_TON = 6 // TON 最大小数位数
|
|
|
-const MAX_DECIMALS_COIN = 2 // 金币最大小数位数
|
|
|
-// 处理 TON 输入
|
|
|
-const handleTonInput = (e: any) => {
|
|
|
- try {
|
|
|
- let value = formatNumberInput(e.detail.value)
|
|
|
- const numValue = Number(value)
|
|
|
-
|
|
|
- // 检查最大值限制
|
|
|
- if (numValue > MAX_TON) {
|
|
|
- value = MAX_TON.toString()
|
|
|
- }
|
|
|
-
|
|
|
- // 更新 TON 输入值
|
|
|
- tonInput.value = value
|
|
|
-
|
|
|
- // 计算对应的金币数量
|
|
|
- if (value && proportion.value) {
|
|
|
- const coins = numValue * proportion.value
|
|
|
- coinInput.value = Number(coins.toFixed(MAX_DECIMALS_COIN)).toString()
|
|
|
- } else {
|
|
|
- coinInput.value = ''
|
|
|
- }
|
|
|
-
|
|
|
- // 输入值校验
|
|
|
- if (!value) {
|
|
|
- showError.value = false
|
|
|
- errorMessage.value = ''
|
|
|
- } else {
|
|
|
- if (numValue < MIN_TON) {
|
|
|
- showError.value = true
|
|
|
- errorMessage.value = i18n.global.t('purse.Minimum') // 'Minimum withdrawal amount is 0.1 TON'
|
|
|
- } else if (numValue > userBalance.value) {
|
|
|
- showError.value = true
|
|
|
- errorMessage.value = i18n.global.t('purse.balance') // 'Insufficient balance'
|
|
|
- } else {
|
|
|
- showError.value = false
|
|
|
- errorMessage.value = ''
|
|
|
- }
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- console.error('Error in handleTonInput:', error)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 处理金币输入
|
|
|
-const handleCoinInput = (e: any) => {
|
|
|
- try {
|
|
|
- let value = formatNumberInput(e.detail.value)
|
|
|
- const numValue = Number(value)
|
|
|
-
|
|
|
- // 检查最大值限制
|
|
|
- const maxCoins = MAX_TON * proportion.value
|
|
|
- if (numValue > maxCoins) {
|
|
|
- value = maxCoins.toString()
|
|
|
- }
|
|
|
-
|
|
|
- // 更新金币输入值
|
|
|
- coinInput.value = value
|
|
|
-
|
|
|
- // 计算对应的 TON 数量
|
|
|
- if (value && proportion.value) {
|
|
|
- const tons = numValue / proportion.value
|
|
|
- tonInput.value = Number(tons.toFixed(MAX_DECIMALS_TON)).toString()
|
|
|
-
|
|
|
- // 根据计算出的 TON 值进行验证
|
|
|
- if (tons < MIN_TON) {
|
|
|
- showError.value = true
|
|
|
- errorMessage.value = i18n.global.t('purse.Minimum')
|
|
|
- } else if (tons > userBalance.value) {
|
|
|
- showError.value = true
|
|
|
- errorMessage.value = i18n.global.t('purse.balance')
|
|
|
- } else {
|
|
|
- showError.value = false
|
|
|
- errorMessage.value = ''
|
|
|
- }
|
|
|
- } else {
|
|
|
- tonInput.value = ''
|
|
|
- showError.value = false
|
|
|
- errorMessage.value = ''
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- console.error('Error in handleCoinInput:', error)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 验证金额 - 仅在提交时使用
|
|
|
-const validateAmount = () => {
|
|
|
- const tonAmount = Number(tonInput.value || 0)
|
|
|
-
|
|
|
- if (!tonInput.value || tonAmount <= 0) {
|
|
|
- errorMessage.value = i18n.global.t('purse.amount')
|
|
|
- showError.value = true
|
|
|
- return false
|
|
|
- }
|
|
|
-
|
|
|
- if (tonAmount < MIN_TON) {
|
|
|
- errorMessage.value = i18n.global.t('purse.Minimum')
|
|
|
- showError.value = true
|
|
|
- return false
|
|
|
- }
|
|
|
-
|
|
|
- if (tonAmount > userBalance.value) {
|
|
|
- errorMessage.value = i18n.global.t('purse.balance')
|
|
|
- showError.value = true
|
|
|
- return false
|
|
|
- }
|
|
|
-
|
|
|
- return true
|
|
|
-}
|
|
|
-
|
|
|
-// 连接钱包
|
|
|
-const triggerConnect = async () => {
|
|
|
- if (!wallet.value) {
|
|
|
- try {
|
|
|
- await open()
|
|
|
- } catch (error) {
|
|
|
- console.error('Connection failed:', error)
|
|
|
- }
|
|
|
- } else {
|
|
|
- handleWithdraw()
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 处理兑换
|
|
|
-const handleWithdraw = async () => {
|
|
|
- if (!validateAmount()) {
|
|
|
- return
|
|
|
- }
|
|
|
- if (!coinAddress.value) {
|
|
|
- return
|
|
|
- }
|
|
|
- try {
|
|
|
- const transaction = {
|
|
|
- validUntil: Math.floor(Date.now() / 1000) + 60,
|
|
|
- messages: [
|
|
|
- {
|
|
|
- address: coinAddress.value,
|
|
|
- // 转换为 nanoTON
|
|
|
- amount: (Number(tonInput.value) * 1000000000).toString(),
|
|
|
- },
|
|
|
- ],
|
|
|
- }
|
|
|
-
|
|
|
- const result = await tonConnectUI.sendTransaction(transaction)
|
|
|
-
|
|
|
- if (result) {
|
|
|
- if (wallet.value?.account?.address) {
|
|
|
- await getWalletBalance(wallet.value.account.address)
|
|
|
- }
|
|
|
- const { code, msg } = await postRechargeCoin({
|
|
|
- coin: (Number(tonInput.value) * 1000000000).toString(),
|
|
|
- coin_address: userFriendlyAddress.value,
|
|
|
- boc: result.boc,
|
|
|
- favorable: '',
|
|
|
- })
|
|
|
- if (code === 1) {
|
|
|
- showNotify({ type: 'success', message: msg })
|
|
|
- } else {
|
|
|
- showNotify({ type: 'warning', message: msg })
|
|
|
- }
|
|
|
- tonInput.value = ''
|
|
|
- coinInput.value = ''
|
|
|
- showError.value = false
|
|
|
- errorMessage.value = ''
|
|
|
- // 刷新记录
|
|
|
- refreshRecords()
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- console.error('Withdrawal failed:', error)
|
|
|
- }
|
|
|
-}
|
|
|
-const pcamaignList = ref<RechargeCoinList[]>([])
|
|
|
-// 刷新记录
|
|
|
-const refreshRecords = async () => {
|
|
|
- try {
|
|
|
- // 这里调用你的API获取最新记录
|
|
|
- const { data } = await postRechargeCoinReturn()
|
|
|
- pcamaignList.value = data
|
|
|
- } catch (error) {
|
|
|
- console.error('Failed to refresh records:', error)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 监听钱包连接状态
|
|
|
-onMounted(async () => {
|
|
|
- await getProportion()
|
|
|
- await getCoinAddressFn()
|
|
|
- await refreshRecords()
|
|
|
- if (wallet.value?.account?.address) {
|
|
|
- console.info('🚀 ~ file:index method: line:296 -----', 1111)
|
|
|
- getWalletBalance(wallet.value.account.address)
|
|
|
-
|
|
|
- if (balanceInterval) clearInterval(balanceInterval)
|
|
|
- balanceInterval = setInterval(() => {
|
|
|
- getWalletBalance(wallet.value.account.address)
|
|
|
- }, 30000)
|
|
|
- } else {
|
|
|
- userBalance.value = 0
|
|
|
- if (balanceInterval) {
|
|
|
- clearInterval(balanceInterval)
|
|
|
- balanceInterval = null
|
|
|
- }
|
|
|
- }
|
|
|
-})
|
|
|
-
|
|
|
-onUnmounted(() => {
|
|
|
- if (balanceInterval) {
|
|
|
- clearInterval(balanceInterval)
|
|
|
- }
|
|
|
- tonConnectUI.removeStatusChangeListener()
|
|
|
-})
|
|
|
-</script>
|
|
|
-
|
|
|
-<style scoped lang="scss">
|
|
|
-.custom-input {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- width: 630rpx;
|
|
|
- height: 100rpx;
|
|
|
- padding-right: 20rpx;
|
|
|
- background-color: white;
|
|
|
- border-radius: 20rpx;
|
|
|
-}
|
|
|
-
|
|
|
-.input-field {
|
|
|
- flex: 1;
|
|
|
- height: 100rpx;
|
|
|
- padding-right: 20rpx;
|
|
|
- font-size: 38rpx;
|
|
|
- line-height: 100rpx;
|
|
|
- color: black;
|
|
|
- text-align: right;
|
|
|
- background: transparent;
|
|
|
-}
|
|
|
-
|
|
|
-/* 修改 placeholder 样式 */
|
|
|
-.input-field::placeholder {
|
|
|
- font-size: 38rpx;
|
|
|
- color: #999;
|
|
|
-}
|
|
|
-
|
|
|
-.btn-bg {
|
|
|
- background: #8ae54a;
|
|
|
-}
|
|
|
-</style>
|
|
|
+<!--<template>-->
|
|
|
+<!-- <view class="w-full min-h-screen bg-bgc flex flex-col items-center text-white">-->
|
|
|
+<!-- <text class="mt-70rpx fw-540 text-[45rpx]">{{ $t('purse.Withdraw') }}</text>-->
|
|
|
+<!-- <!– 余额显示 –>-->
|
|
|
+<!-- <view class="w-690rpx h-538rpx rounded-30rpx bg-[#27272A] flex items-center flex-col mt-45rpx">-->
|
|
|
+<!-- <!– TON输入框 –>-->
|
|
|
+<!-- <view class="custom-input mt-30rpx">-->
|
|
|
+<!-- <image src="@/static/images/purse/u.png" class="w-70rpx h-70rpx ml-14rpx"></image>-->
|
|
|
+<!-- <input-->
|
|
|
+<!-- type="text"-->
|
|
|
+<!-- v-model="tonInput"-->
|
|
|
+<!-- @input="handleTonInput"-->
|
|
|
+<!-- placeholder="0"-->
|
|
|
+<!-- class="input-field"-->
|
|
|
+<!-- />-->
|
|
|
+<!-- </view>-->
|
|
|
+
|
|
|
+<!-- <!– 提示信息 –>-->
|
|
|
+<!-- <text-->
|
|
|
+<!-- class="text-26rpx text-left w-full mt-30rpx ml-56rpx"-->
|
|
|
+<!-- :class="{ 'text-red-500': showError }"-->
|
|
|
+<!-- >-->
|
|
|
+<!-- {{ errorMessage || i18n.global.t('purse.Minimum') }}-->
|
|
|
+<!-- </text>-->
|
|
|
+
|
|
|
+<!-- <!– 金币输入框 –>-->
|
|
|
+<!-- <view class="custom-input mt-40rpx">-->
|
|
|
+<!-- <image src="@/static/images/purse/blackGB.png" class="w-70rpx h-70rpx ml-14rpx"></image>-->
|
|
|
+<!-- <input-->
|
|
|
+<!-- type="text"-->
|
|
|
+<!-- v-model="coinInput"-->
|
|
|
+<!-- @input="handleCoinInput"-->
|
|
|
+<!-- placeholder="Enter withdrawal address"-->
|
|
|
+<!-- class="input-field"-->
|
|
|
+<!-- />-->
|
|
|
+<!-- </view>-->
|
|
|
+
|
|
|
+<!-- <!– 连接钱包/提现按钮 –>-->
|
|
|
+<!-- <view-->
|
|
|
+<!-- @click="triggerConnect"-->
|
|
|
+<!-- class="w-630rpx h-100rpx rounded-20rpx btn-bg mt-60rpx flex items-center justify-center cursor-pointer"-->
|
|
|
+<!-- >-->
|
|
|
+<!-- <text class="text-32rpx text-white">{{ wallet ? 'Withdraw' : 'Connect' }}</text>-->
|
|
|
+<!-- </view>-->
|
|
|
+<!-- </view>-->
|
|
|
+<!-- <!– 记录刷新区 –>-->
|
|
|
+<!-- <view class="w-690rpx mt-49rpx flex items-center justify-between">-->
|
|
|
+<!-- <text>{{ $t('purse.Record') }}</text>-->
|
|
|
+<!-- <image-->
|
|
|
+<!-- @click="refreshRecords"-->
|
|
|
+<!-- src="@/static/images/purse/shuaxin.png"-->
|
|
|
+<!-- class="w-42rpx h-42rpx"-->
|
|
|
+<!-- ></image>-->
|
|
|
+<!-- </view>-->
|
|
|
+<!-- <view-->
|
|
|
+<!-- v-for="(record, index) in pcamaignList"-->
|
|
|
+<!-- :key="index"-->
|
|
|
+<!-- class="w-690rpx h-130rpx mt-30rpx rounded-20rpx bg-[#13355A] flex items-center justify-between mt-20rpx"-->
|
|
|
+<!-- >-->
|
|
|
+<!-- <view class="flex items-center ml-20rpx justify-between w-full">-->
|
|
|
+<!-- <view>-->
|
|
|
+<!-- <image src="@/static/images/purse/blackGB.png" class="w-70rpx h-70rpx mr-29rpx" />-->
|
|
|
+<!-- <text class="text-24rpx text-white mr-20rpx">{{ record.pay_time }}</text>-->
|
|
|
+<!-- </view>-->
|
|
|
+
|
|
|
+<!-- <view class="flex items-center">-->
|
|
|
+<!-- <text class="text-24rpx text-white mr-40rpx">+{{ record.coin_exchange }}</text>-->
|
|
|
+<!-- </view>-->
|
|
|
+<!-- </view>-->
|
|
|
+<!-- </view>-->
|
|
|
+<!-- </view>-->
|
|
|
+<!-- <wd-notify />-->
|
|
|
+<!--</template>-->
|
|
|
+
|
|
|
+<!--<script setup lang="ts">-->
|
|
|
+<!--import {-->
|
|
|
+<!-- useTonWallet,-->
|
|
|
+<!-- useTonConnectUI,-->
|
|
|
+<!-- useTonConnectModal,-->
|
|
|
+<!-- useTonAddress,-->
|
|
|
+<!--} from '@townsquarelabs/ui-vue'-->
|
|
|
+<!--import { useTelegramBackButton } from '@/hooks/useTelegramBackButton'-->
|
|
|
+<!--import {-->
|
|
|
+<!-- getCoinAddress,-->
|
|
|
+<!-- getRecharge,-->
|
|
|
+<!-- postRechargeCoin,-->
|
|
|
+<!-- postRechargeCoinReturn,-->
|
|
|
+<!-- RechargeCoinList,-->
|
|
|
+<!--} from '@/service/purse'-->
|
|
|
+<!--import i18n from '@/locale/index'-->
|
|
|
+<!--import { useNotify } from 'wot-design-uni'-->
|
|
|
+
|
|
|
+<!--const { showNotify } = useNotify()-->
|
|
|
+<!--const { open, close } = useTonConnectModal()-->
|
|
|
+<!--const { isVisible } = useTelegramBackButton(() => {-->
|
|
|
+<!-- uni.navigateBack()-->
|
|
|
+<!--})-->
|
|
|
+<!--const userFriendlyAddress = useTonAddress()-->
|
|
|
+<!--// 状态管理-->
|
|
|
+<!--const wallet = useTonWallet()-->
|
|
|
+<!--const { tonConnectUI } = useTonConnectUI()-->
|
|
|
+<!--const tonInput = ref('') // TON 输入值-->
|
|
|
+<!--const coinInput = ref('') // 金币输入值-->
|
|
|
+<!--const userBalance = ref(0)-->
|
|
|
+<!--const errorMessage = ref('')-->
|
|
|
+<!--const showError = ref(false)-->
|
|
|
+<!--const inputMode = ref('ton') // 当前输入模式: 'ton' | 'coin'-->
|
|
|
+
|
|
|
+<!--// 计算最小提现金额(以nanoTON为单位)-->
|
|
|
+<!--const MIN_WITHDRAWAL = 0.1 // 1 TON-->
|
|
|
+
|
|
|
+<!--let balanceInterval: number | null = null-->
|
|
|
+
|
|
|
+<!--// 获取钱包余额-->
|
|
|
+<!--const getWalletBalance = async (address: string) => {-->
|
|
|
+<!-- try {-->
|
|
|
+<!-- const response = await fetch(-->
|
|
|
+<!-- `https://toncenter.com/api/v2/getAddressBalance?address=${address}`,-->
|
|
|
+<!-- )-->
|
|
|
+<!-- const data = await response.json()-->
|
|
|
+
|
|
|
+<!-- if (data.ok) {-->
|
|
|
+<!-- userBalance.value = Number(data.result) / 1000000000-->
|
|
|
+<!-- console.log('Wallet balance:', userBalance.value, 'TON')-->
|
|
|
+<!-- } else {-->
|
|
|
+<!-- console.error('Failed to get balance, invalid response:', data)-->
|
|
|
+<!-- userBalance.value = 0-->
|
|
|
+<!-- }-->
|
|
|
+<!-- } catch (error) {-->
|
|
|
+<!-- console.error('Failed to fetch balance:', error)-->
|
|
|
+<!-- userBalance.value = 0-->
|
|
|
+<!-- }-->
|
|
|
+<!--}-->
|
|
|
+
|
|
|
+<!--// 获取兑换比例-->
|
|
|
+<!--const proportion = ref(0)-->
|
|
|
+<!--const getProportion = async () => {-->
|
|
|
+<!-- const { data } = await getRecharge()-->
|
|
|
+<!-- proportion.value = data.proportion-->
|
|
|
+<!--}-->
|
|
|
+
|
|
|
+<!--// 获取系统充值钱包地址-->
|
|
|
+<!--const coinAddress = ref()-->
|
|
|
+<!--const getCoinAddressFn = async () => {-->
|
|
|
+<!-- const { data } = await getCoinAddress()-->
|
|
|
+<!-- coinAddress.value = data.coin_address-->
|
|
|
+<!--}-->
|
|
|
+
|
|
|
+<!--const formatNumberInput = (value: string) => {-->
|
|
|
+<!-- // 移除非数字和小数点-->
|
|
|
+<!-- value = value.replace(/[^\d.]/g, '')-->
|
|
|
+
|
|
|
+<!-- // 处理前导零-->
|
|
|
+<!-- if (value.startsWith('0') && value.length > 1 && !value.startsWith('0.')) {-->
|
|
|
+<!-- value = value.replace(/^0+/, '')-->
|
|
|
+<!-- }-->
|
|
|
+
|
|
|
+<!-- // 如果是第一次输入小数点且在开头,自动补0-->
|
|
|
+<!-- if (value.startsWith('.')) {-->
|
|
|
+<!-- value = '0' + value-->
|
|
|
+<!-- }-->
|
|
|
+
|
|
|
+<!-- // 限制只能有一个小数点-->
|
|
|
+<!-- if (value.includes('.') && value.split('.').length > 2) {-->
|
|
|
+<!-- return value.substring(0, value.lastIndexOf('.'))-->
|
|
|
+<!-- }-->
|
|
|
+
|
|
|
+<!-- // 限制小数位数为6位-->
|
|
|
+<!-- if (value.includes('.')) {-->
|
|
|
+<!-- const [integer, decimal] = value.split('.')-->
|
|
|
+<!-- return `${integer}.${decimal.slice(0, 6)}`-->
|
|
|
+<!-- }-->
|
|
|
+
|
|
|
+<!-- return value-->
|
|
|
+<!--}-->
|
|
|
+<!--// 常量定义-->
|
|
|
+<!--const MIN_TON = 0.1 // 最小兑换数量改为 0.1 TON-->
|
|
|
+<!--const MAX_TON = 1000000 // 最大 TON 输入限制-->
|
|
|
+<!--const MAX_DECIMALS_TON = 6 // TON 最大小数位数-->
|
|
|
+<!--const MAX_DECIMALS_COIN = 2 // 金币最大小数位数-->
|
|
|
+<!--// 处理 TON 输入-->
|
|
|
+<!--const handleTonInput = (e: any) => {-->
|
|
|
+<!-- try {-->
|
|
|
+<!-- let value = formatNumberInput(e.detail.value)-->
|
|
|
+<!-- const numValue = Number(value)-->
|
|
|
+
|
|
|
+<!-- // 检查最大值限制-->
|
|
|
+<!-- if (numValue > MAX_TON) {-->
|
|
|
+<!-- value = MAX_TON.toString()-->
|
|
|
+<!-- }-->
|
|
|
+
|
|
|
+<!-- // 更新 TON 输入值-->
|
|
|
+<!-- tonInput.value = value-->
|
|
|
+
|
|
|
+<!-- // 计算对应的金币数量-->
|
|
|
+<!-- if (value && proportion.value) {-->
|
|
|
+<!-- const coins = numValue * proportion.value-->
|
|
|
+<!-- coinInput.value = Number(coins.toFixed(MAX_DECIMALS_COIN)).toString()-->
|
|
|
+<!-- } else {-->
|
|
|
+<!-- coinInput.value = ''-->
|
|
|
+<!-- }-->
|
|
|
+
|
|
|
+<!-- // 输入值校验-->
|
|
|
+<!-- if (!value) {-->
|
|
|
+<!-- showError.value = false-->
|
|
|
+<!-- errorMessage.value = ''-->
|
|
|
+<!-- } else {-->
|
|
|
+<!-- if (numValue < MIN_TON) {-->
|
|
|
+<!-- showError.value = true-->
|
|
|
+<!-- errorMessage.value = i18n.global.t('purse.Minimum') // 'Minimum withdrawal amount is 0.1 TON'-->
|
|
|
+<!-- } else if (numValue > userBalance.value) {-->
|
|
|
+<!-- showError.value = true-->
|
|
|
+<!-- errorMessage.value = i18n.global.t('purse.balance') // 'Insufficient balance'-->
|
|
|
+<!-- } else {-->
|
|
|
+<!-- showError.value = false-->
|
|
|
+<!-- errorMessage.value = ''-->
|
|
|
+<!-- }-->
|
|
|
+<!-- }-->
|
|
|
+<!-- } catch (error) {-->
|
|
|
+<!-- console.error('Error in handleTonInput:', error)-->
|
|
|
+<!-- }-->
|
|
|
+<!--}-->
|
|
|
+
|
|
|
+<!--// 处理金币输入-->
|
|
|
+<!--const handleCoinInput = (e: any) => {-->
|
|
|
+<!-- try {-->
|
|
|
+<!-- let value = formatNumberInput(e.detail.value)-->
|
|
|
+<!-- const numValue = Number(value)-->
|
|
|
+
|
|
|
+<!-- // 检查最大值限制-->
|
|
|
+<!-- const maxCoins = MAX_TON * proportion.value-->
|
|
|
+<!-- if (numValue > maxCoins) {-->
|
|
|
+<!-- value = maxCoins.toString()-->
|
|
|
+<!-- }-->
|
|
|
+
|
|
|
+<!-- // 更新金币输入值-->
|
|
|
+<!-- coinInput.value = value-->
|
|
|
+
|
|
|
+<!-- // 计算对应的 TON 数量-->
|
|
|
+<!-- if (value && proportion.value) {-->
|
|
|
+<!-- const tons = numValue / proportion.value-->
|
|
|
+<!-- tonInput.value = Number(tons.toFixed(MAX_DECIMALS_TON)).toString()-->
|
|
|
+
|
|
|
+<!-- // 根据计算出的 TON 值进行验证-->
|
|
|
+<!-- if (tons < MIN_TON) {-->
|
|
|
+<!-- showError.value = true-->
|
|
|
+<!-- errorMessage.value = i18n.global.t('purse.Minimum')-->
|
|
|
+<!-- } else if (tons > userBalance.value) {-->
|
|
|
+<!-- showError.value = true-->
|
|
|
+<!-- errorMessage.value = i18n.global.t('purse.balance')-->
|
|
|
+<!-- } else {-->
|
|
|
+<!-- showError.value = false-->
|
|
|
+<!-- errorMessage.value = ''-->
|
|
|
+<!-- }-->
|
|
|
+<!-- } else {-->
|
|
|
+<!-- tonInput.value = ''-->
|
|
|
+<!-- showError.value = false-->
|
|
|
+<!-- errorMessage.value = ''-->
|
|
|
+<!-- }-->
|
|
|
+<!-- } catch (error) {-->
|
|
|
+<!-- console.error('Error in handleCoinInput:', error)-->
|
|
|
+<!-- }-->
|
|
|
+<!--}-->
|
|
|
+
|
|
|
+<!--// 验证金额 - 仅在提交时使用-->
|
|
|
+<!--const validateAmount = () => {-->
|
|
|
+<!-- const tonAmount = Number(tonInput.value || 0)-->
|
|
|
+
|
|
|
+<!-- if (!tonInput.value || tonAmount <= 0) {-->
|
|
|
+<!-- errorMessage.value = i18n.global.t('purse.amount')-->
|
|
|
+<!-- showError.value = true-->
|
|
|
+<!-- return false-->
|
|
|
+<!-- }-->
|
|
|
+
|
|
|
+<!-- if (tonAmount < MIN_TON) {-->
|
|
|
+<!-- errorMessage.value = i18n.global.t('purse.Minimum')-->
|
|
|
+<!-- showError.value = true-->
|
|
|
+<!-- return false-->
|
|
|
+<!-- }-->
|
|
|
+
|
|
|
+<!-- if (tonAmount > userBalance.value) {-->
|
|
|
+<!-- errorMessage.value = i18n.global.t('purse.balance')-->
|
|
|
+<!-- showError.value = true-->
|
|
|
+<!-- return false-->
|
|
|
+<!-- }-->
|
|
|
+
|
|
|
+<!-- return true-->
|
|
|
+<!--}-->
|
|
|
+
|
|
|
+<!--// 连接钱包-->
|
|
|
+<!--const triggerConnect = async () => {-->
|
|
|
+<!-- if (!wallet.value) {-->
|
|
|
+<!-- try {-->
|
|
|
+<!-- await open()-->
|
|
|
+<!-- } catch (error) {-->
|
|
|
+<!-- console.error('Connection failed:', error)-->
|
|
|
+<!-- }-->
|
|
|
+<!-- } else {-->
|
|
|
+<!-- handleWithdraw()-->
|
|
|
+<!-- }-->
|
|
|
+<!--}-->
|
|
|
+
|
|
|
+<!--// 处理兑换-->
|
|
|
+<!--const handleWithdraw = async () => {-->
|
|
|
+<!-- if (!validateAmount()) {-->
|
|
|
+<!-- return-->
|
|
|
+<!-- }-->
|
|
|
+<!-- if (!coinAddress.value) {-->
|
|
|
+<!-- return-->
|
|
|
+<!-- }-->
|
|
|
+<!-- try {-->
|
|
|
+<!-- const transaction = {-->
|
|
|
+<!-- validUntil: Math.floor(Date.now() / 1000) + 60,-->
|
|
|
+<!-- messages: [-->
|
|
|
+<!-- {-->
|
|
|
+<!-- address: coinAddress.value,-->
|
|
|
+<!-- // 转换为 nanoTON-->
|
|
|
+<!-- amount: (Number(tonInput.value) * 1000000000).toString(),-->
|
|
|
+<!-- },-->
|
|
|
+<!-- ],-->
|
|
|
+<!-- }-->
|
|
|
+
|
|
|
+<!-- const result = await tonConnectUI.sendTransaction(transaction)-->
|
|
|
+
|
|
|
+<!-- if (result) {-->
|
|
|
+<!-- if (wallet.value?.account?.address) {-->
|
|
|
+<!-- await getWalletBalance(wallet.value.account.address)-->
|
|
|
+<!-- }-->
|
|
|
+<!-- const { code, msg } = await postRechargeCoin({-->
|
|
|
+<!-- coin: (Number(tonInput.value) * 1000000000).toString(),-->
|
|
|
+<!-- coin_address: userFriendlyAddress.value,-->
|
|
|
+<!-- boc: result.boc,-->
|
|
|
+<!-- favorable: '',-->
|
|
|
+<!-- })-->
|
|
|
+<!-- if (code === 1) {-->
|
|
|
+<!-- showNotify({ type: 'success', message: msg })-->
|
|
|
+<!-- } else {-->
|
|
|
+<!-- showNotify({ type: 'warning', message: msg })-->
|
|
|
+<!-- }-->
|
|
|
+<!-- tonInput.value = ''-->
|
|
|
+<!-- coinInput.value = ''-->
|
|
|
+<!-- showError.value = false-->
|
|
|
+<!-- errorMessage.value = ''-->
|
|
|
+<!-- // 刷新记录-->
|
|
|
+<!-- refreshRecords()-->
|
|
|
+<!-- }-->
|
|
|
+<!-- } catch (error) {-->
|
|
|
+<!-- console.error('Withdrawal failed:', error)-->
|
|
|
+<!-- }-->
|
|
|
+<!--}-->
|
|
|
+<!--const pcamaignList = ref<RechargeCoinList[]>([])-->
|
|
|
+<!--// 刷新记录-->
|
|
|
+<!--const refreshRecords = async () => {-->
|
|
|
+<!-- try {-->
|
|
|
+<!-- // 这里调用你的API获取最新记录-->
|
|
|
+<!-- const { data } = await postRechargeCoinReturn()-->
|
|
|
+<!-- pcamaignList.value = data-->
|
|
|
+<!-- } catch (error) {-->
|
|
|
+<!-- console.error('Failed to refresh records:', error)-->
|
|
|
+<!-- }-->
|
|
|
+<!--}-->
|
|
|
+
|
|
|
+<!--// 监听钱包连接状态-->
|
|
|
+<!--onMounted(async () => {-->
|
|
|
+<!-- await getProportion()-->
|
|
|
+<!-- await getCoinAddressFn()-->
|
|
|
+<!-- await refreshRecords()-->
|
|
|
+<!-- if (wallet.value?.account?.address) {-->
|
|
|
+<!-- console.info('🚀 ~ file:index method: line:296 -----', 1111)-->
|
|
|
+<!-- getWalletBalance(wallet.value.account.address)-->
|
|
|
+
|
|
|
+<!-- if (balanceInterval) clearInterval(balanceInterval)-->
|
|
|
+<!-- balanceInterval = setInterval(() => {-->
|
|
|
+<!-- getWalletBalance(wallet.value.account.address)-->
|
|
|
+<!-- }, 30000)-->
|
|
|
+<!-- } else {-->
|
|
|
+<!-- userBalance.value = 0-->
|
|
|
+<!-- if (balanceInterval) {-->
|
|
|
+<!-- clearInterval(balanceInterval)-->
|
|
|
+<!-- balanceInterval = null-->
|
|
|
+<!-- }-->
|
|
|
+<!-- }-->
|
|
|
+<!--})-->
|
|
|
+
|
|
|
+<!--onUnmounted(() => {-->
|
|
|
+<!-- if (balanceInterval) {-->
|
|
|
+<!-- clearInterval(balanceInterval)-->
|
|
|
+<!-- }-->
|
|
|
+<!-- tonConnectUI.removeStatusChangeListener()-->
|
|
|
+<!--})-->
|
|
|
+<!--</script>-->
|
|
|
+
|
|
|
+<!--<style scoped lang="scss">-->
|
|
|
+<!--.custom-input {-->
|
|
|
+<!-- display: flex;-->
|
|
|
+<!-- align-items: center;-->
|
|
|
+<!-- width: 630rpx;-->
|
|
|
+<!-- height: 100rpx;-->
|
|
|
+<!-- padding-right: 20rpx;-->
|
|
|
+<!-- background-color: white;-->
|
|
|
+<!-- border-radius: 20rpx;-->
|
|
|
+<!--}-->
|
|
|
+
|
|
|
+<!--.input-field {-->
|
|
|
+<!-- flex: 1;-->
|
|
|
+<!-- height: 100rpx;-->
|
|
|
+<!-- padding-right: 20rpx;-->
|
|
|
+<!-- font-size: 38rpx;-->
|
|
|
+<!-- line-height: 100rpx;-->
|
|
|
+<!-- color: black;-->
|
|
|
+<!-- text-align: right;-->
|
|
|
+<!-- background: transparent;-->
|
|
|
+<!--}-->
|
|
|
+
|
|
|
+<!--/* 修改 placeholder 样式 */-->
|
|
|
+<!--.input-field::placeholder {-->
|
|
|
+<!-- font-size: 38rpx;-->
|
|
|
+<!-- color: #999;-->
|
|
|
+<!--}-->
|
|
|
+
|
|
|
+<!--.btn-bg {-->
|
|
|
+<!-- background: #8ae54a;-->
|
|
|
+<!--}-->
|
|
|
+<!--</style>-->
|