1
李凌
9 days ago 349c48e168b9f2580334422228acde7d1b21bede
src/views/cryptos/loan/index.vue
@@ -1,239 +1,213 @@
<template>
  <div id="cryptos">
    <div class="loan">
    <div class="loan-page">
      <assets-head :title="$t('助力贷')">
        <div class="right flex items-center">
          <img src="@/assets/image/loan/rule.png" alt="rule-img" class="w-50 h-50 mr-20"
          <img src="@/assets/image/loan/rule.png" alt="rule-img" class="head-icon mr-20"
            @click="$router.push('/cryptos/loanRule')" />
          <img src="@/assets/image/loan/history.png" alt="exchange-img" class="w-50 h-50"
          <img src="@/assets/image/loan/history.png" alt="history-img" class="head-icon"
            @click="$router.push('/cryptos/loanHistory')" />
        </div>
      </assets-head>
      <!--   container -->
      <div class="container px-32">
        <!--      title-->
        <div class="py-30">
          <span style="color: #E35461;">{{ this.$t('经过平台审核,您可向平台申请一笔借款!') }}</span>
      <div class="loan-body">
        <!-- 额度展示 -->
        <div class="hero-card">
          <div class="hero-badge">{{ $t('最高可借') }}</div>
          <div class="hero-amount">
            <span class="amount-num">{{ formatNum(loanData.maxQuota) }}</span>
            <span class="amount-unit">USDT</span>
          </div>
          <p class="hero-tip">{{ $t('经过平台审核,您可向平台申请一笔借款!') }}</p>
        </div>
        <!--    list  -->
        <div class="loanList">
          <div class="flex justify-between py-30 border-b-color">
            <div>
              <span class="grayText">{{ $t('期望借款金额') }}</span>
            </div>
            <div class="flex align-center">
              <!--            <input class="font-600 textColor border-none text-right mr-14 mainBackground" v-model="loanAmount"  disabled="disabled" @input="inputAmunt" />-->
              <span class="mr-14 font-600 textColor">{{ loanData.maxQuota || 0 }}</span>
              <span class="font-600 textColor">USDT</span>
            </div>
          </div>
          <div class="flex justify-between py-30 border-b-color">
            <div>
              <span class="grayText">{{ $t('还款周期') }}</span>
            </div>
            <div class="flex align-center">
              <!--            <div class="font-600 textColor relative">-->
              <div class="font-600 mr-14 textColor relative" @click="isSelectDay = !isSelectDay">
                <span>{{ loanData.term }} {{ $t('天') }}</span>
                <!--              <div class="selectDay"  v-show="isSelectDay">-->
                <!--                <div class="mb-20 border-b-white" v-for="(s,index) in selectDayList" :key="index"  @click="selectDay(s)">-->
                <!--                  <span>{{s}}</span>-->
                <!--                </div>-->
                <!--              </div>-->
              </div>
              <div class="w-24 h-24">
                <img src="@/assets/image/loan/right.png" alt="right-img" class="w-full">
              </div>
            </div>
          </div>
          <div class="flex justify-between py-30 border-b-color">
            <div>
              <span class="grayText">{{ $t('日利率') }}</span>
            </div>
            <div class="flex align-center">
              <span class="font-600 textColor">{{ loanData.dailyRate * 1 * 100 || 0 }}%</span>
            </div>
          </div>
          <div class="flex justify-between py-30 border-b-color">
            <div>
              <span class="grayText">{{ $t('还款方式') }}</span>
            </div>
            <div class="flex align-center">
              <span class="font-600 textColor text-right">{{ $t('到期一次还款') }}</span>
            </div>
          </div>
          <div class="flex justify-between py-30 border-b-color">
            <div>
              <span class="grayText">{{ $t('利息') }}</span>
            </div>
            <div class="flex align-center">
              <!--            借款金额*日利率*借款天数-->
              <!-- <span class="font-600 textColor">{{$bigDecimal.multiply(+loanData.maxQuota , +loanData.dailyRate) * +this.loanData.term || 0 }} USDT</span> -->
              <span class="font-600 textColor">{{ (+loanData.maxQuota, +loanData.dailyRate) * +this.loanData.term || 0 }}
                USDT</span>
            </div>
          </div>
          <div class="flex justify-between py-30 border-b-color">
            <div>
              <span class="grayText">{{ $t('放款机构') }}</span>
            </div>
            <div class="flex align-center">
              <span class="font-600 textColor">{{ loanData.lendingName }}</span>
            </div>
          </div>
        </div>
        <!--      上传区域-->
        <div class="uploadImg">
          <div class="mb-40 textColor">
            <span>{{ $t('信用放款(请确保图片清晰可见)') }}</span>
          </div>
          <div class="upload">
            <div class="flex mt-33 mb-80 justify-between">
              <div class="flex-1 flex flex-col text-center justify-center items-center">
                <div class="upload-wrap">
                  <!--                    <img src="@/assets/image/kyc/0.png" alt="" class="w-full"-->
                  <!--                         v-if="[1, 2].includes(status) && frontFile.length === 0" />-->
                  <van-uploader v-model="frontFile" multiple :max-count="1" :disabled="isUpload" :after-read="afterRead"
                    @click-upload="onClickUpload('frontFile')" />
                </div>
                <div class="mt-32 font-26 h-20" style="color:#868D9A;">{{ $t('证件正面') }}</div>
              </div>
              <div class="flex-1 flex flex-col text-center justify-center items-center">
                <div class="upload-wrap">
                  <!--                    <img src="@/assets/image/kyc/1.png" alt="" class="w-full"-->
                  <!--                         v-if="[1, 2].includes(status) && reverseFile.length === 0" />-->
                  <van-uploader v-model="reverseFile" multiple :max-count="1" :disabled="isUpload" :after-read="afterRead"
                    @click-upload="onClickUpload('reverseFile')" />
                </div>
                <div class="mt-32 font-26 h-20" style="color:#868D9A;">{{ $t('证件反面') }}</div>
              </div>
            </div>
            <div class="flex mt-33 mb-80 justify-between">
              <div class="flex-1 flex flex-col text-center justify-center items-center">
                <div class="upload-wrap">
                  <!--                    <img src="@/assets/image/kyc/2.png" alt="" class="w-full"-->
                  <!--                         v-if="[1, 2].includes(status) && fileList.length === 0" />-->
                  <van-uploader v-model="fileList" multiple :max-count="1" :disabled="isUpload" :after-read="afterRead"
                    @click-upload="onClickUpload('fileList')" />
                </div>
                <div class="mt-32 font-26 h-20" style="color:#868D9A;">{{ $t('手持证件照') }}</div>
              </div>
              <div class="flex-1 flex flex-col text-center justify-center items-center">
                <div class="upload-wrap">
                  <img src="@/assets/image/loan/handId.png" alt="" class="w-full" />
                </div>
                <div class="mt-32 font-26 h-20" style="color:#868D9A;">{{ $t('拍摄示例') }}</div>
              </div>
        <!-- 期限选择 -->
        <div class="section-card">
          <div class="section-title">{{ $t('选择借款期限') }}</div>
          <div class="term-list">
            <div
              v-for="item in loanDeployList"
              :key="item.uuid || item.id || item.term"
              class="term-item"
              :class="{ active: isSamePlan(item) }"
              @click="selectDay(item)"
            >
              <span class="term-days">{{ item.term }}</span>
              <span class="term-unit">{{ $t('天') }}</span>
            </div>
          </div>
        </div>
        <!--      确认按钮-->
        <div class="confirmBtn btnMain w-full py-30 text-center text-white font-400 font-32" @click="submit()">
          <span>{{ $t('确定') }}</span>
        <!-- 方案详情 -->
        <div class="section-card">
          <div class="section-title">{{ $t('借款方案') }}</div>
          <div class="info-grid">
            <div class="info-row">
              <span class="info-label">{{ $t('期望借款金额') }}</span>
              <span class="info-value highlight">{{ formatNum(loanData.maxQuota) }} USDT</span>
            </div>
            <div class="info-row">
              <span class="info-label">{{ $t('还款周期') }}</span>
              <span class="info-value">{{ loanData.term || 0 }} {{ $t('天') }}</span>
            </div>
            <div class="info-row">
              <span class="info-label">{{ $t('日利率') }}</span>
              <span class="info-value">{{ dailyRatePercent }}%</span>
            </div>
            <div class="info-row">
              <span class="info-label">{{ $t('预计总利息') }}</span>
              <span class="info-value accent">{{ totalInterest }} USDT</span>
            </div>
            <div class="info-row">
              <span class="info-label">{{ $t('还款方式') }}</span>
              <span class="info-value">{{ $t('到期一次还款') }}</span>
            </div>
            <div class="info-row">
              <span class="info-label">{{ $t('放款机构') }}</span>
              <span class="info-value">{{ loanData.lendingName || '-' }}</span>
            </div>
          </div>
        </div>
        <!-- 证件上传 -->
        <div class="section-card upload-section">
          <div class="section-title">{{ $t('身份认证') }}</div>
          <p class="upload-tip">{{ $t('信用放款(请确保图片清晰可见)') }}</p>
          <div class="upload-grid">
            <div class="upload-item">
              <div class="upload-wrap">
                <van-uploader
                  v-model="frontFile"
                  multiple
                  :max-count="1"
                  :deletable="!isUpload"
                  :disabled="isUpload"
                  :after-read="afterRead"
                  @click-upload="onClickUpload('frontFile')"
                />
              </div>
              <span class="upload-label">{{ $t('credentFront') }}</span>
            </div>
            <div class="upload-item">
              <div class="upload-wrap">
                <van-uploader
                  v-model="reverseFile"
                  multiple
                  :max-count="1"
                  :deletable="!isUpload"
                  :disabled="isUpload"
                  :after-read="afterRead"
                  @click-upload="onClickUpload('reverseFile')"
                />
              </div>
              <span class="upload-label">{{ $t('credentObverse') }}</span>
            </div>
          </div>
        </div>
      </div>
      <van-popup v-model:show="isSelectDay" position="bottom" :round="true">
        <ul class="bg-white">
          <li v-for="(day, index) in loanDeployList" class="text-center py-30" :key="index" @click="selectDay(day)">
            <span>{{ day.term }}</span>
          </li>
        </ul>
      </van-popup>
      <div class="submit-bar">
        <button class="submit-btn" :disabled="isUpload" @click="submit">
          {{ $t('提交申请') }}
        </button>
      </div>
    </div>
  </div>
</template>
<script>
import AssetsHead from "@/components/Transform/assets-head/index.vue";
import { Popup, Uploader, showToast } from "vant";
import { _uploadImage, _getLoan, _loanApply } from "@/service/fund.api";
// import {debounce} from "@/utils/utis";
import { Uploader, showToast } from "vant";
import { _getLoan, _loanApply } from "@/service/fund.api";
import { _uploadImage } from "@/service/upload.api";
export default {
  name: "loanIndex",
  components: {
    AssetsHead,
    [Uploader.name]: Uploader,
    [Popup.name]: Popup,
  },
  computed: {
    dailyRatePercent() {
      const rate = Number(this.loanData.dailyRate) || 0;
      return (rate * 100).toFixed(2);
    },
    totalInterest() {
      const quota = Number(this.loanData.maxQuota) || 0;
      const rate = Number(this.loanData.dailyRate) || 0;
      const term = Number(this.loanData.term) || 0;
      return (quota * rate * term).toFixed(2);
    },
  },
  methods: {
    formatNum(val) {
      const n = Number(val) || 0;
      return n.toLocaleString(undefined, { maximumFractionDigits: 2 });
    },
    isSamePlan(item) {
      const key = item.uuid || item.id || item.term;
      const cur = this.loanData.uuid || this.loanData.id || this.loanData.term;
      return key === cur;
    },
    getLoan() {
      _getLoan().then(data => {
        this.loanDeployList = data
        this.loanDeployList.sort((a, b) => {
          return +a.term - +b.term
        })
        this.loanData = this.loanDeployList[0]
      })
        this.loanDeployList = (data || []).sort((a, b) => +a.term - +b.term);
        if (this.loanDeployList.length) {
          this.loanData = this.loanDeployList[0];
        }
      });
    },
    submit() {
      // console.log('this.frontFile',this.frontFile)
      if (!this.frontFile.length || !this.reverseFile.length || !this.fileList.length) {
        showToast(this.$t('请上传完整证件信息'))
        return
      if (!this.frontFile.length || !this.reverseFile.length) {
        showToast(this.$t('请上传证件正反面'));
        return;
      }
      if (!this.frontFile[0].resURL || !this.reverseFile[0].resURL) {
        showToast(this.$t('uploading'));
        return;
      }
      _loanApply({
        ...this.loanData,
        // term:this.loanData.term,
        quota: this.loanData.maxQuota,//借贷金额 取max
        // dailyRate: this.loanData.dailyRate,
        // lendingInstitution:this.loanData.lendingInstitution,//放款机构名字
        // lendingName:this.loanData.lendingName,
        // repayment:this.loanData.repayment,//还款方式
        // repayCycle:this.loanData.repayCycle, //还款日期
        uuid: this.loanData.uuid || this.loanData.id,
        quota: this.loanData.maxQuota,
        symbol: 'USDT',
        frontFile: this.frontFile[0].resURL,
        reverseFile: this.reverseFile[0].resURL,
        fileList: this.fileList[0].resURL,
      }).then(res => {
        // console.log('res',res)
        this.$router.push('/cryptos/loanHistory')
      }).then(() => {
        showToast(this.$t('提交成功'));
        this.$router.push('/cryptos/loanHistory');
      }).catch(err => {
        showToast(this.$t(err.msg))
      })
        showToast(err.msg || this.$t('提交失败'));
      });
    },
    // //防抖
    // inputAmunt(){
    //   this.loanAmount = this.loanAmount.replace(/[^0-9]/g, '')
    //   this.debounceFn()
    // },
    // debounceFn: debounce(function () {
    //   this.getInterest()
    // }, 500),
    // getInterest(){
    //   this.interest = +this.loanAmount * +this.loanRate
    // },
    selectDay(data) {
      this.loanData = data
      // this.getInterest()
      this.isSelectDay = false
      this.loanData = data;
    },
    onClickUpload(type) {
      this.curFile = type
      this.curFile = type;
    },
    afterRead(file) { /// 处理文件
      // console.log(file)
      file.status = 'uploading'
      file.message = this.$t('上传中...')
      this.isUpload = true
    afterRead(file) {
      file.status = 'uploading';
      file.message = this.$t('uploading');
      this.isUpload = true;
      _uploadImage(file).then(data => {
        file.status = 'success';
        file.message = this.$t('上传成功');
        file.resURL = data
        this[this.curFile] = [file]
        this.isUpload = false
      }).catch(err => {
        file.message = this.$t('uploadSuccess');
        file.resURL = data;
        if (this.curFile === 'frontFile') {
          this.frontFile = [file];
        } else {
          this.reverseFile = [file];
        }
        this.isUpload = false;
      }).catch(() => {
        file.status = 'failed';
        file.message = this.$t('图片上传失败');
        this.isUpload = false
      })
        file.message = this.$t('uploadFailed');
        this.isUpload = false;
      });
    },
  },
  mounted() {
    this.getLoan()
    // this.getInterest()
    this.getLoan();
  },
  data() {
    return {
@@ -241,65 +215,259 @@
      loanDeployList: [],
      frontFile: [],
      reverseFile: [],
      fileList: [],
      curFile: 'frontFile',
      // resultArr: ['small-success_' + this.$t('已申请未审核'), 'identifing_' + this.$t('审核中'), 'small-success_' + this.$t('审核通过'), 'icon-close_' + this.$t('审核未通过')], // 0 好像是未提交
      // status:'',
      isSelectDay: false,
      isUpload: false,
    }
  }
}
    };
  },
};
</script>
<style scoped lang="scss">
@import "@/assets/init.scss";
#cryptos {
  .loan {
    width: 100%;
  .loan-page {
    min-height: 100vh;
    padding-bottom: 160px;
    box-sizing: border-box;
  }
  .uploadImg {
    margin-top: 60px;
  .head-icon {
    width: 50px;
    height: 50px;
  }
    .upload-wrap {
      width: 356px;
      height: 288px;
      display: flex;
      justify-content: center;
      align-items: center;
  .loan-body {
    padding: 24px 32px 0;
  }
      ::v-deep .van-uploader__upload {
        width: 356px !important;
        height: 288px !important;
      }
  .hero-card {
    padding: 40px 36px;
    border-radius: 24px;
    background: linear-gradient(135deg, #1a6dff 0%, #004aee 55%, #0035b8 100%);
    color: #fff;
    box-shadow: 0 16px 40px rgba(0, 74, 238, 0.28);
    margin-bottom: 28px;
  }
  .hero-badge {
    display: inline-block;
    padding: 8px 20px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.18);
    font-size: 24px;
    margin-bottom: 24px;
  }
  .hero-amount {
    display: flex;
    align-items: baseline;
    gap: 12px;
    margin-bottom: 16px;
  }
  .amount-num {
    font-size: 72px;
    font-weight: 700;
    line-height: 1;
  }
  .amount-unit {
    font-size: 32px;
    font-weight: 600;
    opacity: 0.9;
  }
  .hero-tip {
    margin: 0;
    font-size: 26px;
    line-height: 1.5;
    opacity: 0.88;
  }
  .section-card {
    padding: 32px 28px;
    border-radius: 20px;
    margin-bottom: 24px;
    @include themify() {
      background: themed("cont_background");
    }
    box-shadow: 0 4px 24px rgba(0, 0, 0, 0.04);
  }
  .section-title {
    font-size: 32px;
    font-weight: 600;
    margin-bottom: 28px;
    @include themify() {
      color: themed("text_color");
    }
  }
  .selectDay {
    position: absolute;
    left: -70px;
    background: #f5f5f5;
    color: #333;
    box-sizing: border-box;
  .term-list {
    display: flex;
    flex-wrap: wrap;
    gap: 20px;
  }
    div {
      padding: 20px 70px;
  .term-item {
    min-width: 120px;
    padding: 20px 28px;
    border-radius: 16px;
    text-align: center;
    border: 2px solid transparent;
    transition: all 0.2s;
    @include themify() {
      background: themed("tab_background");
      color: themed("text_color2");
    }
    div:last-child {
    &.active {
      border-color: #004aee;
      background: rgba(0, 74, 238, 0.08);
      color: #004aee;
    }
  }
  .term-days {
    font-size: 40px;
    font-weight: 700;
    margin-right: 4px;
  }
  .term-unit {
    font-size: 24px;
  }
  .info-grid {
    display: flex;
    flex-direction: column;
    gap: 0;
  }
  .info-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 24px 0;
    border-bottom: 1px solid rgba(134, 142, 155, 0.15);
    &:last-child {
      border-bottom: none;
      margin-bottom: 0;
      padding-bottom: 0;
    }
    &:first-child {
      padding-top: 0;
    }
  }
  .confirmBtn {
    border-radius: 8px;
  .info-label {
    font-size: 28px;
    color: #868e9b;
  }
  .grayText {
    color: #868E9B;
  .info-value {
    font-size: 28px;
    font-weight: 600;
    text-align: right;
    max-width: 55%;
    @include themify() {
      color: themed("text_color");
    }
    &.highlight {
      color: #004aee;
      font-size: 30px;
    }
    &.accent {
      color: #e35461;
    }
  }
  .upload-section {
    margin-bottom: 0;
  }
  .upload-tip {
    margin: -12px 0 28px;
    font-size: 26px;
    color: #868e9b;
    line-height: 1.5;
  }
  .upload-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 24px;
  }
  .upload-item {
    display: flex;
    flex-direction: column;
    align-items: center;
  }
  .upload-wrap {
    width: 100%;
    height: 220px;
    border-radius: 16px;
    overflow: hidden;
    border: 2px dashed rgba(0, 74, 238, 0.25);
    background: rgba(0, 74, 238, 0.03);
    display: flex;
    align-items: center;
    justify-content: center;
    ::v-deep .van-uploader,
    ::v-deep .van-uploader__wrapper,
    ::v-deep .van-uploader__upload,
    ::v-deep .van-uploader__preview,
    ::v-deep .van-uploader__preview-image {
      width: 100% !important;
      height: 220px !important;
      margin: 0 !important;
    }
    ::v-deep .van-uploader__upload-icon {
      font-size: 48px;
      color: #004aee;
    }
  }
  .upload-label {
    margin-top: 16px;
    font-size: 26px;
    color: #868d9a;
  }
  .submit-bar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 24px 32px calc(24px + env(safe-area-inset-bottom));
    @include themify() {
      background: themed("footer_background");
    }
    box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.06);
    z-index: 20;
  }
  .submit-btn {
    width: 100%;
    height: 96px;
    border: none;
    border-radius: 16px;
    background: linear-gradient(90deg, #1a6dff, #004aee);
    color: #fff;
    font-size: 32px;
    font-weight: 600;
    &:disabled {
      opacity: 0.6;
    }
  }
}
</style>
</style>