1
jhzh
2026-05-22 ef52095f5e9f0a9fe2da779bb1573947d77d75b6
src/views/cryptos/Recharge/rechargeList.vue
@@ -1,147 +1,466 @@
<template>
  <div id="cryptos">
    <div class="recharge box-border">
      <assets-head :title="$t('充值通道')" v-if="!isForeign" :back-func="backFunc">
        <img src="../../../assets/image/assets-center/exchange.png" alt="exchange-img" class="w-44 h-38"
          @click="goRouter('/cryptos/assetsCenter/rechargeWithdrawRecord')" />
      </assets-head>
      <assets-head v-else :title="$t('充值通道')" >
        <img src="../../../assets/image/assets-center/exchange.png" alt="exchange-img" class="w-44 h-38"
          @click="goRouter('/cryptos/assetsCenter/rechargeWithdrawRecord')" />
      </assets-head>
      <div class="pl-36 pr-36">
        <div class="recharge-title font-35 textColor">{{ $t('请选择充值币种') }}</div>
        <div class="recharge-list flex justify-between">
          <div class="item-view flex flex-col items-center justify-center text-center w-189 h-220 box-border"
            @click="selectSymbol('usdt')">
            <img src="../../../assets/image/symbol/usdt.png" class="w-92 h-92" />
            <div class="text-grey font-26 mt-32">{{ $t('USDT充值') }}</div>
          </div>
          <div class="item-view  flex flex-col items-center justify-center text-center w-189 h-220 box-border"
            @click="selectSymbol('btc')">
            <img src="../../../assets/image/symbol/btc.png" class="w-92 h-92" />
            <div class="text-grey font-26 mt-32">{{ $t('BTC充值') }}</div>
          </div>
          <div class="item-view flex flex-col items-center justify-center text-center w-189 h-220 box-border"
            @click="selectSymbol('eth')">
            <img src="../../../assets/image/symbol/eth.png" class="w-92 h-92" />
            <div class="text-grey font-26 mt-32">{{ $t('ETH充值') }}</div>
  <div id="cryptos" class="deposit-page">
    <assets-head :title="$t('订金')" :show-left="true" :back-func="onBack">
      <template v-if="step === 'list'">
        <img
          src="../../../assets/image/assets-center/exchange.png"
          alt=""
          class="deposit-head-icon"
          @click="goRouter('/cryptos/assetsCenter/rechargeWithdrawRecord')"
        />
      </template>
    </assets-head>
    <!-- 图一:列表 -->
    <template v-if="step === 'list'">
      <div class="deposit-body">
        <div class="deposit-search-wrap">
          <van-icon name="search" class="deposit-search-icon" />
          <input
            v-model="searchKeyword"
            type="text"
            class="deposit-search-input"
            :placeholder="$t('search')"
          />
        </div>
        <div class="deposit-section-title">{{ $t('Popular coins') }}</div>
        <div class="deposit-popular">
          <div class="deposit-coin-btn" @click="selectCoin('usdt')">USDT</div>
        </div>
        <div class="deposit-section-title">{{ $t('List of coins') }}</div>
        <div class="deposit-coin-list">
          <div
            v-for="item in filteredCoins"
            :key="item.symbol"
            class="deposit-coin-item"
            @click="selectCoin(item.symbol)"
          >
            <img :src="`${HOST_URL}/symbol/${item.symbol}.png`" alt="" class="deposit-coin-icon" />
            <span class="deposit-coin-symbol">{{ item.symbol.toUpperCase() }}</span>
          </div>
        </div>
      </div>
      <!-- <div class="textColor mt-40">
        <div class="pl-36 pr-36 h-90 lh-90 border-b-color flex justify-between font-28" v-for="(item, index) in list"
          :key="index" @click="toPath(item.url)">
          <div class="flex items-center">
            <img :src="handleImage(item.imgPath)" class="w-44 h-44 rounded-full mr-20" />
            <span class="textColor">{{ item.name }} {{ $t('官方充值通道') }}</span>
          </div>
          <div>
            <van-icon class="textColor" name="arrow" />
    </template>
    <!-- 图二:已选币种 + 选择网络 -->
    <template v-else>
      <div class="deposit-body deposit-body-selected">
        <div class="deposit-card" @click="step = 'list'">
          <img :src="`${HOST_URL}/symbol/${selectedSymbol}.png`" alt="" class="deposit-card-icon" />
          <span class="deposit-card-symbol">{{ selectedSymbol.toUpperCase() }}</span>
          <van-icon name="arrow" class="deposit-card-arrow" />
        </div>
        <div class="deposit-card deposit-card-network">
          <div class="deposit-network-label">{{ $t('Deposit network') }}</div>
          <div class="deposit-choice-btn" @click="showNetworkSheet = true">
            <span class="deposit-choice-text">{{ selectedChain ? selectedChain.blockchain_name : $t('Choice Network') }}</span>
            <van-icon name="arrow-down" class="deposit-choice-arrow" />
          </div>
        </div>
      </div> -->
    </div>
        <!-- 选中网络后下方显示充值详情 -->
        <div v-if="selectedChain && selectedChain.address" class="deposit-detail">
          <div class="deposit-detail-qr-wrap">
            <canvas ref="qrcodeCanvas" class="deposit-detail-qr"></canvas>
          </div>
          <div class="deposit-detail-address-label">{{ $t('Deposit address') }}:</div>
          <div class="deposit-detail-address-row">
            <span class="deposit-detail-address-text">{{ selectedChain.address }}</span>
            <img :src="copyImg" alt="copy" class="deposit-detail-copy-btn" @click="copyAddress" />
          </div>
        </div>
      </div>
    </template>
    <!-- 图三:底部弹框 选择充值链 -->
    <van-action-sheet
      v-model:show="showNetworkSheet"
      class="deposit-sheet"
    >
      <div class="deposit-sheet-content">
        <div class="deposit-sheet-head">
          <span class="deposit-sheet-title">{{ $t('Choice Network') }}</span>
          <van-icon name="cross" class="deposit-sheet-close" @click="showNetworkSheet = false" />
        </div>
        <p class="deposit-sheet-tip">
          {{ $t('Tip: choose a network consistent with the withdraw platform to top up, otherwise you will lose this funds') }}
        </p>
        <div
          v-for="(chain, index) in chainList"
          :key="index"
          class="deposit-sheet-item"
          @click="onSelectChain(chain)"
        >
          {{ chain.blockchain_name }}
        </div>
      </div>
    </van-action-sheet>
  </div>
</template>
<script>
import assetsHead from "@/components/Transform/assets-head/index.vue";
import { Icon } from 'vant';
import QRCode from 'qrcode';
import { showToast } from 'vant';
import assetsHead from '@/components/Transform/assets-head/index.vue';
import { HOST_URL } from '@/config';
import Axios from '@/service/recharge.js';
import copyImg from '@/assets/imgs/new/copy.png';
const COINS = [
  { symbol: 'usdt', name: 'USDT' },
  { symbol: 'usdc', name: 'USDC' },
  { symbol: 'btc', name: 'BTC' },
  { symbol: 'eth', name: 'ETH' },
];
export default {
  name: 'rechageList',
  components: {
    assetsHead,
    [Icon.name]: Icon,
  },
  components: { assetsHead },
  data() {
    return {
      list: [
        {
          name: 'Huobi',
          url: 'https://www.huobi.com/en-us/',
          imgPath: new URL('@/assets/image/huobi.png', import.meta.url),
        },
        {
          name: 'Binance',
          url: 'https://www.binance.com/en',
          imgPath: new URL('@/assets/image/bian.png', import.meta.url),
        },
        {
          name: 'Coinbase',
          url: 'https://www.coinbase.com/',
          imgPath: new URL('@/assets/image/coinbase.png', import.meta.url),
        },
        {
          name: 'Crypto',
          url: 'https://www.crypto.com/',
          imgPath: new URL('@/assets/image/crypto.png', import.meta.url),
        }
      ],
      isForeign: false
    }
      HOST_URL,
      step: 'list',
      searchKeyword: '',
      selectedSymbol: '',
      chainList: [],
      selectedChain: null,
      showNetworkSheet: false,
      isForeign: false,
      copyImg,
    };
  },
  computed: {
    filteredCoins() {
      const k = (this.searchKeyword || '').trim().toLowerCase();
      if (!k) return COINS;
      return COINS.filter((c) => c.symbol.toLowerCase().includes(k) || c.name.toLowerCase().includes(k));
    },
  },
  created() {
    if (this.$route.query.isForeign) {
      this.isForeign = this.$route.query.isForeign
      this.isForeign = this.$route.query.isForeign;
    }
  },
  methods: {
    handleImage(url) {
      return new URL(url, import.meta.url).href
    onBack() {
      if (this.step === 'selected') {
        this.step = 'list';
        this.selectedSymbol = '';
        this.selectedChain = null;
        this.chainList = [];
      } else {
        this.$router.push('/quotes/index?tabActive=1');
      }
    },
    toPath(url) {
      const a = document.createElement('a');
      a.href = url;
      a.target = "_bank";
      document.body.append(a);
      a.click();
      document.body.removeChild(a)
      // if (navigator.userAgent.search('Html5Plus') != -1) {
      //     plus.runtime.openURL(url)
      // } else {
      //     window.open(url)
      // }
    selectCoin(symbol) {
      this.selectedSymbol = symbol;
      this.selectedChain = null;
      this.chainList = [];
      Axios.getBlock({ coin: symbol })
        .then((res) => {
          this.chainList = Array.isArray(res) ? res : [];
          this.step = 'selected';
        })
        .catch(() => {
          this.chainList = [];
          this.step = 'selected';
        });
    },
    backFunc() {
      this.$router.push('/quotes/index?tabActive=1')
    onSelectChain(chain) {
      this.selectedChain = chain;
      this.showNetworkSheet = false;
      this.$nextTick(() => this.drawQR());
    },
    selectSymbol(symbol) {
      this.$router.push({
        path: "/cryptos/recharge/rechargePage",
        query: {
          'symbol': symbol
        }
      });
    drawQR() {
      if (!this.selectedChain || !this.selectedChain.address || !this.$refs.qrcodeCanvas) return;
      const opts = {
        errorCorrectionLevel: 'H',
        width: 200,
        margin: 4,
        color: { dark: '#333333', light: '#fff' },
      };
      QRCode.toCanvas(this.$refs.qrcodeCanvas, this.selectedChain.address, opts, () => {});
    },
    goRouter(params) {
      this.$router.push({
        path: params,
        query: {
          back: "1"
        }
      });
    }
  }
}
    copyAddress() {
      const address = this.selectedChain?.address;
      if (!address) return;
      if (typeof navigator !== 'undefined' && navigator.clipboard && navigator.clipboard.writeText) {
        navigator.clipboard.writeText(address).then(() => showToast(this.$t('复制成功'))).catch(() => this.copyFallback(address));
      } else {
        this.copyFallback(address);
      }
    },
    copyAddressFallback(text) {
      this.copyFallback(text);
    },
    copyFallback(text) {
      const textarea = document.createElement('textarea');
      textarea.value = text;
      textarea.style.position = 'fixed';
      textarea.style.opacity = '0';
      document.body.appendChild(textarea);
      textarea.select();
      try {
        document.execCommand('copy');
        showToast(this.$t('复制成功'));
      } catch (e) {}
      document.body.removeChild(textarea);
    },
    goRouter(path) {
      this.$router.push({ path, query: { back: '1' } });
    },
  },
};
</script>
<style lang="scss" scoped>
@import "@/assets/init.scss";
.deposit-page {
  min-height: 100vh;
  background: #fff !important;
  padding-bottom: 2.5rem;
}
.deposit-head-icon {
  width: 1.375rem;
  height: 1.1875rem;
}
#cryptos {
  .recharge {
    width: 100%;
    box-sizing: border-box;
  }
.deposit-body {
  padding: 1rem 1.5rem;
}
.deposit-body-selected {
  padding-top: 1.5rem;
}
  .recharge-title {
    margin: 86px 0 104px 0;
  }
/* 图一:搜索 */
.deposit-search-wrap {
  display: flex;
  align-items: center;
  height: 3.25rem;
  padding: 0 1rem;
  background: #f5f5f5;
  border-radius: 0.5rem;
  margin-bottom: 1.5rem;
}
.deposit-search-icon {
  color: #999;
  font-size: 28px;
  margin-right: 0.75rem;
}
.deposit-search-input {
  flex: 1;
  border: none;
  background: transparent;
  font-size: 28px;
  outline: none;
}
.deposit-search-input::placeholder {
  color: #9b9b9b;
}
  .recharge-list>div {
    border: 2px solid $bg_dark;
    border-radius: 15px;
    box-sizing: border-box;
  }
.deposit-section-title {
  font-size: 26px;
  color: #9b9b9b;
  margin-bottom: 0.75rem;
}
.deposit-popular {
  margin-bottom: 1.5rem;
}
.deposit-coin-btn {
  display: inline-block;
  padding: 0.875rem 1.75rem;
  background: #f5f5f5;
  border-radius: 0.5rem;
  font-size: 28px;
  color: #333;
  cursor: pointer;
}
.deposit-coin-list {
  display: flex;
  flex-direction: column;
  gap: 0;
}
.deposit-coin-item {
  display: flex;
  align-items: center;
  padding: 1.125rem 0;
  border-bottom: 1px solid #f0f0f0;
  cursor: pointer;
}
.deposit-coin-item:last-child {
  border-bottom: none;
}
.deposit-coin-icon {
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  margin-right: 1rem;
}
.deposit-coin-symbol {
  font-size: 28px;
  color: #333;
  font-weight: 500;
}
/* 图二:卡片 */
.deposit-card {
  background: #f6f6f6;
  border-radius: 0.5rem;
  padding: 1.25rem;
  margin-bottom: 1.5rem;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
}
/* 第一个卡片:图标+币种+箭头同一行 */
.deposit-card:first-child {
  cursor: pointer;
  display: flex;
  align-items: center;
}
.deposit-card:first-child .deposit-card-icon {
  flex-shrink: 0;
}
.deposit-card:first-child .deposit-card-symbol {
  flex: 1;
  min-width: 0;
}
.deposit-card:first-child .deposit-card-arrow {
  flex-shrink: 0;
  margin-top: 0;
}
.deposit-card-network {
  cursor: default;
}
.deposit-card-icon {
  width: 3.25rem;
  height: 3.25rem;
  border-radius: 50%;
  margin-right: 1rem;
  vertical-align: middle;
}
.deposit-card-symbol {
  font-size: 28px;
  color: #333;
  font-weight: 600;
  vertical-align: middle;
}
.deposit-card-arrow {
  color: #999;
  font-size: 28px;
}
.deposit-network-label {
  font-size: 26px;
  color: #9b9b9b;
  margin-bottom: 0.625rem;
}
.deposit-choice-btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.875rem 10px;
  border-radius: 10px;
  cursor: pointer;
  background-color: #fff;
}
.deposit-choice-text {
  font-size: 28px;
  color: #333;
}
.deposit-choice-arrow {
  color: #999;
  font-size: 28px;
}
.deposit-next-btn {
  width: 100%;
  height: 3.5rem;
  margin-top: 1.5rem;
  border: none;
  border-radius: 0.5rem;
  background: linear-gradient(90deg, #a443cf, #5e2bc8);
  color: #fff;
  font-size: 28px;
  font-weight: 600;
  cursor: pointer;
}
/* 图三:底部弹框 */
.deposit-sheet-content {
  padding: 0 1.5rem 2rem;
  background-color: #fff;
}
.deposit-sheet-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 2.5rem  0.75rem;
  margin-bottom: 0.75rem;
}
.deposit-sheet-title {
  font-size: 35px;
  font-weight: 600;
  color: #333;
}
.deposit-sheet-close {
  font-size: 28px;
  color: #999;
  cursor: pointer;
}
.deposit-sheet-tip {
  font-size: 26px;
  line-height: 1.5;
  margin-bottom: 1.75rem;
  padding: 20px 10px;
  background-color: #F6F6F6;
}
.deposit-sheet-item {
  padding: 2rem 1.5rem;
  border-radius: 1rem;
  margin-bottom: 0.75rem;
  font-size: 35px;
  color: #333;
  cursor: pointer;
  border: 1px solid #f2f2f2;
}
.deposit-sheet-item:last-child {
  margin-bottom: 0;
}
/* 充值详情:二维码 + 地址(选中网络后下方显示) */
.deposit-detail {
  margin-top: 1.5rem;
  padding: 1.5rem 0;
  border-top: 1px solid #f0f0f0;
  text-align: left;
}
.deposit-detail-qr-wrap {
  display: flex;
  justify-content: center;
  margin-bottom: 1.25rem;
}
.deposit-detail-qr {
  display: block;
}
.deposit-detail-address-label {
  font-size: 26px;
  color: #9b9b9b;
  margin-bottom: 0.5rem;
}
.deposit-detail-address-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}
.deposit-detail-address-text {
  flex: 1;
  min-width: 0;
  font-size: 26px;
  color: #333;
  word-break: break-all;
}
.deposit-detail-copy-btn {
  width: 2.5rem;
  height: 2.5rem;
  cursor: pointer;
  flex-shrink: 0;
  object-fit: contain;
}
</style>