Pārlūkot izejas kodu

ar管理-兑换、提现

xiaomei 1 gadu atpakaļ
vecāks
revīzija
50fec2bbcb

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 729 - 1242
package-lock.json


+ 33 - 0
src/api/home.js

@@ -533,4 +533,37 @@ export default {
       data
     })
   },
+  //AR兑换提交
+  arExchange(data) {
+    return request.request({
+      url: '/user/arExchange',
+      method: "post",
+      headers: {
+        'Lang': localStorage.getItem('lang') || '',
+      },
+      data
+    })
+  },
+  //AR金额数据
+  arInfo(data) {
+    return request.request({
+      url: '/user/arInfo',
+      method: "post",
+      headers: {
+        'Lang': localStorage.getItem('lang') || '',
+      },
+      data
+    })
+  },
+  //AR提现
+  arSubmit(data) {
+    return request.request({
+      url: '/user/arSubmit',
+      method: "post",
+      headers: {
+        'Lang': localStorage.getItem('lang') || '',
+      },
+      data
+    })
+  },
 }

+ 9 - 0
src/router/index.js

@@ -36,6 +36,7 @@ import buyRecord from '../views/service/buyRecord.vue';  //购买服务器记录
 // import etcExchange from '../views/mine/etcExchange.vue';  //etc兑换页面
 import etcManage from '../views/mine/etcManage.vue';  //etc管理页面
 import smhManage from '../views/mine/smhManage.vue';  //smh管理页面
+import arManage from '../views/mine/arManage.vue';  //ar管理页面
 Vue.use(VueRouter);
 const routes = [
 
@@ -257,6 +258,14 @@ const routes = [
           requiresAuth: true
         }
       },
+      {
+        path: 'arManage',
+        name: 'arManage',
+        component: arManage,
+        meta: {
+          requiresAuth: true
+        }
+      },
     ],
   },
 ];

+ 292 - 0
src/views/mine/arExchange.vue

@@ -0,0 +1,292 @@
+<template>
+  <div>
+    <!-- <div class="head">
+      <img @click="back" src="@/assets/images/back.png" class="arrow_img" />
+      <span>SMH兑换</span>
+    </div> -->
+    <div class="lease">
+      <div class="balance_box">
+        <div>
+          <span class="text_active">AR余额</span>
+        </div>
+        <!-- 钱包余额 -->
+        <div class="balance">
+          <span>{{ Math.floor(dataObj.ar * 100) / 100 || 0 }}</span>
+        </div>
+        <div class="universal">
+          <div class="slider">
+            <!-- <van-slider v-model="amount" :max="max" :min="400" bar-height="8" active-color="#238be8" button-size="16" /> -->
+            <input type="number" v-model="exchangeAmount" placeholder="请输入兑换数量" />
+            <div class="all" @click="exchangeAmount = dataObj.ar">
+              <span>全部</span>
+            </div>
+          </div>
+          <!-- <div>
+            <span class="hint"></span>
+          </div> -->
+          <!-- <div class="slider">
+            <input type="text" v-model="address" :disabled="disable" placeholder="请输入提币地址" />
+          </div> -->
+          <div class="li">
+            <span>手续费:{{ Number(dataObj.ar_exchange_ratio) * 100 || 0 }}%</span>
+          </div>
+          <div class="li">
+            <span>{{
+              `预计兑换: ${Math.floor(Number(exchangeAmount) * Number(dataObj.ar_price) * (1 - Number(dataObj.ar_exchange_ratio) * 1) * 100) / 100 || 0}U(1AR = ${Math.floor(Number(dataObj.ar_price) * 100) / 100 || 0}U)`
+            }}</span>
+          </div>
+        </div>
+      </div>
+      <!-- <div class="button" v-if="tabIndex == 1">
+          <van-button class="submit_button" type="primary" v-if="showApprove" @click="approve">授权</van-button>
+          <van-button class="submit_button" type="primary" v-else @click="submit">提交</van-button>
+        </div> -->
+      <div class="button">
+        <van-button class="submit_button" type="primary" @click="arExchange">提交</van-button>
+      </div>
+    </div>
+    <!-- 加载弹窗 -->
+    <van-popup v-model="isApprove" round style="width: 80%" :close-on-click-overlay="false">
+      <div class="bind_box">
+        <div style="font-weight: bold"><van-loading type="spinner" /></div>
+        <div class="address_field">处理中...</div>
+      </div>
+    </van-popup>
+  </div>
+</template>
+  
+  <script>
+import { homeApi } from '@/api/index';
+import { Notify } from 'vant';
+import packApi from '@/methods/pack.js';
+import usdt from '@/methods/usdt.js';
+import { useErc20Contract } from '@/utils/useContract';
+import { MaxUint256 } from '@ethersproject/constants';
+import { getErc20Contract, getJackPairContract } from '@/utils/contractHelp';
+import { formatAmount, parseAmount, accMul, gasProcessing } from '@/utils/format.js'; //有空看看这里 这个地方封装了bignumer处理 好
+import { mapState } from 'vuex';
+import Web3 from 'web3';
+import { number } from 'echarts';
+export default {
+  data() {
+    return {
+      show: true,
+      address: '', //地址
+      payToken: undefined, //支付币种
+      walletBalance: 0, //钱包余额
+      showApprove: false, //授权
+      isApprove: false, //是否有授权
+
+      tabIndex: 1, // 1:兑换 2:提现
+      dataObj: {
+        ar: 0,
+        ar_min_amount: 0,
+        tips: null,
+      },
+      max: 0,
+      system_money: 0, //系统余额
+      min: 0,
+      allowanceV2: 0, // 授权额度
+      withdrawAmount: null,
+      disable: false,
+      exchangeAmount: null,
+    };
+  },
+  created() {
+    this.init();
+  },
+  watch: {
+    account() {
+      this.init();
+    },
+    amount(e) {
+      if (String(e).indexOf('.') != -1) {
+        this.amount = Math.trunc(e);
+      }
+      // if (/[^1-9]/g.test(e)) {
+      //   return false;
+      // }
+    },
+  },
+  computed: {
+    ...mapState(['account']),
+  },
+  methods: {
+    init() {
+      homeApi.arInfo().then(res => {
+        console.log(res);
+        if (res.code == 200) {
+          this.dataObj = res.data;
+          this.address = res.data.address;
+          this.address ? (this.disable = true) : (this.disable = false);
+        }
+      });
+    },
+    changeTab(e) {
+      this.tabIndex = e;
+    },
+    //返回上一页
+    back() {
+      this.$router.back();
+    },
+    arExchange() {
+      if (!this.exchangeAmount) {
+        this.$toast('请输入数量');
+        return;
+      }
+      if (this.exchangeAmount > Number(this.dataObj.ar)) {
+        this.$toast('余额不足');
+        return;
+      }
+      let params = {
+        amount: this.exchangeAmount,
+      };
+      homeApi.arExchange(params).then(res => {
+        if (res.code == 200) {
+          Notify({ type: 'primary', message: res.msg });
+          this.exchangeAmount = '';
+          this.init();
+        } else {
+          Notify({ message: res.msg });
+        }
+      });
+    },
+  },
+};
+</script>
+  
+<style lang="less" scoped>
+.head {
+  position: fixed;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: rgba(#000, 0.8);
+  letter-spacing: 1.5px;
+  font-weight: 550;
+  padding: 14px 0;
+  top: 0;
+  width: 100%;
+  background: #fff;
+  .arrow_img {
+    position: absolute;
+    left: 20px;
+    width: 10px;
+    height: 16px;
+  }
+}
+.lease {
+  // min-height: 100vh;
+  padding: 0 16px 0;
+
+  .balance_box {
+    border-radius: 16px;
+    padding: 10px 20px 30px;
+    overflow: hidden;
+    box-shadow: 4px 4px 15px 0px rgba(180, 212, 212, 0.59);
+    background-color: rgba(255, 255, 255, 0.3);
+    .caption {
+      display: flex;
+      justify-content: space-around;
+      font-size: 14px;
+      color: rgba(102, 102, 102, 1);
+      .system_text {
+        padding: 0 6px 5px;
+        border-bottom: 2px solid rgb(255, 255, 255);
+      }
+      .text_active {
+        color: rgba(35, 139, 232, 1);
+        padding: 0 6px 5px;
+        border-bottom: 2px solid rgba(35, 139, 232, 1);
+      }
+    }
+    .text_active {
+      font-size: 14px;
+      color: rgba(35, 139, 232, 1);
+    }
+    .balance {
+      font-size: 20px;
+      font-weight: bold;
+      color: #000;
+      margin: 12px 0 16px;
+    }
+    .universal {
+      display: flex;
+      // align-items: center;
+      flex-direction: column;
+      // justify-content: space-between;
+      font-size: 14px;
+      color: rgba(102, 102, 102, 1);
+      margin-top: 12px;
+      .li {
+        display: flex;
+        flex-direction: column;
+        line-height: 150%;
+        letter-spacing: 1px;
+        font-size: 13px;
+        padding-top: 6px;
+        // align-items: center;
+        .li_amount {
+          // font-weight: bold;
+          color: #000;
+          margin-top: 8px;
+        }
+      }
+    }
+    .slider {
+      margin: 10px 0 18px;
+      display: flex;
+      align-items: center;
+      input {
+        border: 0;
+        background-color: #f1f1f1;
+        width: 100%;
+        padding: 10px 10px;
+        border-radius: 6px;
+        font-size: 14px;
+        color: #000;
+      }
+      .danwei {
+        font-size: 13px;
+        padding-left: 6px;
+      }
+    }
+    .hint {
+      font-size: 12px;
+      color: rgba(102, 102, 102, 1);
+      padding-left: 6px;
+    }
+  }
+  .button {
+    display: flex;
+    justify-content: center;
+    .submit_button {
+      color: rgba(#fff, 0.95);
+      background: #2f46d4;
+      border: 0;
+      border-radius: 12px;
+      padding: 12px 0;
+      width: 100%;
+      margin-top: 30px;
+      letter-spacing: 1.5px;
+    }
+  }
+}
+.bind_box {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: 50px 0;
+  .address_field {
+    padding-top: 16px;
+  }
+}
+.all {
+  font-size: 10px;
+  white-space: nowrap;
+  padding: 6px;
+  border: 1px solid #238be8;
+  border-radius: 10px;
+  margin-left: 10px;
+}
+</style>

+ 126 - 0
src/views/mine/arManage.vue

@@ -0,0 +1,126 @@
+<template>
+  <div class="house">
+    <div class="head">
+      <img @click="back" src="@/assets/images/back.png" class="arrow_img" />
+      <span>AR管理</span>
+    </div>
+    <div class="tab">
+      <div class="tab_item" :class="tabIndex == index ? 'tab_active' : ''" v-for="(item, index) in tabList" :key="index" @click="changeTab(index)">
+        <span>{{ item }}</span>
+      </div>
+    </div>
+    <ar-exchange v-if="tabIndex == 0"></ar-exchange>
+    <ar-withdraw v-else></ar-withdraw>
+
+    <!-- 加载弹窗 -->
+    <van-popup v-model="isApprove" round style="width: 80%" :close-on-click-overlay="false">
+      <div class="bind_box">
+        <div style="font-weight: bold"><van-loading type="spinner" /></div>
+        <div class="address_field">处理中...</div>
+      </div>
+    </van-popup>
+  </div>
+</template>
+    
+<script>
+import { mapState } from 'vuex';
+import ArExchange from './arExchange.vue';
+import ArWithdraw from './arWithdraw.vue';
+export default {
+  components: {
+    ArExchange,
+    ArWithdraw,
+  },
+  data() {
+    return {
+      token: null, //余额
+      show: true,
+      address: '', //地址
+      payToken: undefined, //支付币种
+      walletBalance: 0, //钱包余额
+      showApprove: false, //授权
+      isApprove: false, //是否有授权
+
+      tabList: ['AR兑换', 'AR提现'],
+      // tabList2: ['钱包余额', '系统余额', '报单算力余额'],
+      tabIndex: 0,
+    };
+  },
+  created() {},
+  watch: {
+    account() {},
+    amount(e) {},
+  },
+  computed: {
+    ...mapState(['account']),
+  },
+  methods: {
+    changeTab(e) {
+      this.tabIndex = e;
+    },
+    //返回上一页
+    back() {
+      this.$router.back();
+    },
+  },
+};
+</script>
+    
+<style lang="less" scoped>
+.house {
+  min-height: calc(100vh - 80px);
+}
+.head {
+  position: fixed;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: rgba(#000, 0.8);
+  letter-spacing: 1.5px;
+  font-weight: 550;
+  padding: 14px 0;
+  top: 0;
+  width: 100%;
+  background: #fff;
+  .arrow_img {
+    position: absolute;
+    left: 20px;
+    width: 10px;
+    height: 16px;
+  }
+}
+.tab {
+  font-size: 14px;
+  display: flex;
+  align-items: center;
+  margin: 80px 16px 32px;
+  background-color: #fff;
+  border-radius: 40px;
+  padding: 4px;
+  box-shadow: 4px 4px 15px 0px rgba(180, 212, 212, 0.59);
+  &_item {
+    text-align: center;
+    color: #000;
+    width: 50%;
+  }
+  &_active {
+    color: #fff;
+    font-weight: 700;
+    padding: 10px 0;
+    background-color: #4159d5;
+    border-radius: 40px;
+  }
+  &_item1 {
+    text-align: center;
+    color: #000;
+    width: 33%;
+  }
+  &_active1 {
+    color: #fff;
+    font-weight: 700;
+    padding: 10px 0;
+    background-color: #4159d5;
+    border-radius: 40px;
+  }
+}
+</style>

+ 313 - 0
src/views/mine/arWithdraw.vue

@@ -0,0 +1,313 @@
+<template>
+  <div>
+    <!-- <div class="head">
+      <img @click="back" src="@/assets/images/back.png" class="arrow_img" />
+      <span>SMH提现</span>
+    </div> -->
+    <div class="lease">
+      <div class="balance_box">
+        <div>
+          <span class="text_active">AR余额</span>
+        </div>
+        <!-- 钱包余额 -->
+        <div class="balance">
+          <span>{{ Math.floor(dataObj.ar * 100) / 100 || 0 }}</span>
+        </div>
+        <div class="universal">
+          <div class="slider">
+            <!-- <van-slider v-model="amount" :max="max" :min="400" bar-height="8" active-color="#238be8" button-size="16" /> -->
+            <input type="number" v-model="withdrawAmount" placeholder="请输入提币金额" />
+            <div class="all" @click="withdrawAmount = dataObj.ar">
+              <span>全部</span>
+            </div>
+          </div>
+          <div>
+            <span class="hint">最小{{ dataObj.ar_min_amount || 0 }}AR起</span>
+          </div>
+          <div class="slider">
+            <textarea type="text" v-model="address" :disabled="disable" placeholder="请输入提币地址" />
+          </div>
+          <div class="li">
+            <span>{{ dataObj.tips }}</span>
+          </div>
+        </div>
+      </div>
+      <!-- <div class="button" v-if="tabIndex == 1">
+          <van-button class="submit_button" type="primary" v-if="showApprove" @click="approve">授权</van-button>
+          <van-button class="submit_button" type="primary" v-else @click="submit">提交</van-button>
+        </div> -->
+      <div class="button">
+        <van-button class="submit_button" type="primary" @click="withdrawSubmit">提交</van-button>
+      </div>
+    </div>
+    <!-- 加载弹窗 -->
+    <van-popup v-model="isApprove" round style="width: 80%" :close-on-click-overlay="false">
+      <div class="bind_box">
+        <div style="font-weight: bold"><van-loading type="spinner" /></div>
+        <div class="address_field">处理中...</div>
+      </div>
+    </van-popup>
+  </div>
+</template>
+  
+  <script>
+import { homeApi } from '@/api/index';
+import { Notify } from 'vant';
+import packApi from '@/methods/pack.js';
+import usdt from '@/methods/usdt.js';
+import { useErc20Contract } from '@/utils/useContract';
+import { MaxUint256 } from '@ethersproject/constants';
+import { getErc20Contract, getJackPairContract } from '@/utils/contractHelp';
+import { formatAmount, parseAmount, accMul, gasProcessing } from '@/utils/format.js'; //有空看看这里 这个地方封装了bignumer处理 好
+import { mapState } from 'vuex';
+import Web3 from 'web3';
+import { number } from 'echarts';
+export default {
+  data() {
+    return {
+      token: null, //余额
+      show: true,
+      address: '', //地址
+      payToken: undefined, //支付币种
+      walletBalance: 0, //钱包余额
+      showApprove: false, //授权
+      isApprove: false, //是否有授权
+
+      tabIndex: 1, // 1:兑换 2:提现
+      dataObj: {
+        token: 0,
+        ar_min_amount: 0,
+        tips: '',
+      },
+      max: 0,
+      system_money: 0, //系统余额
+      min: 0,
+      allowanceV2: 0, // 授权额度
+      withdrawAmount: null,
+      disable: false,
+      exchangeAmount: null,
+    };
+  },
+  created() {
+    this.init();
+  },
+  watch: {
+    account() {
+      this.init();
+    },
+    amount(e) {
+      if (String(e).indexOf('.') != -1) {
+        this.amount = Math.trunc(e);
+      }
+      // if (/[^1-9]/g.test(e)) {
+      //   return false;
+      // }
+    },
+  },
+  computed: {
+    ...mapState(['account']),
+  },
+  methods: {
+    init() {
+      homeApi.arInfo().then(res => {
+        console.log(res);
+        if (res.code == 200) {
+          this.dataObj = res.data;
+          this.address = res.data.address;
+          this.address ? (this.disable = true) : (this.disable = false);
+        }
+      });
+    },
+    changeTab(e) {
+      this.tabIndex = e;
+    },
+    //返回上一页
+    back() {
+      this.$router.back();
+    },
+
+    withdrawSubmit() {
+      if (!this.withdrawAmount) {
+        this.$toast('请输入金额');
+        return;
+      }
+      if (this.withdrawAmount < Number(this.dataObj.ar_min_amount)) {
+        this.$toast(`最小${this.dataObj.ar_min_amount}SMH`);
+        return;
+      }
+      if (this.withdrawAmount > Number(this.dataObj.ar)) {
+        this.$toast('余额不足');
+        return;
+      }
+
+      if (!this.address) {
+        this.$toast('请输入提币地址');
+        return;
+      }
+      let web3 = new Web3(window.web3.currentProvider);
+      web3.eth.personal.sign(web3.utils.fromUtf8('EtcWithdraw'), this.account, (err, res) => {
+        let params = {
+          amount: this.withdrawAmount,
+          sign: res,
+          address: this.address,
+        };
+        homeApi.arSubmit(params).then(res => {
+          if (res.code == 200) {
+            Notify({ type: 'primary', message: res.msg });
+            this.withdrawAmount = '';
+            this.init();
+          } else {
+            Notify({ message: res.msg });
+          }
+        });
+      });
+    },
+  },
+};
+</script>
+  
+<style lang="less" scoped>
+.head {
+  position: fixed;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: rgba(#000, 0.8);
+  letter-spacing: 1.5px;
+  font-weight: 550;
+  padding: 14px 0;
+  top: 0;
+  width: 100%;
+  background: #fff;
+  .arrow_img {
+    position: absolute;
+    left: 20px;
+    width: 10px;
+    height: 16px;
+  }
+}
+.lease {
+  // min-height: 100vh;
+  padding: 0 16px 0;
+
+  .balance_box {
+    border-radius: 16px;
+    padding: 10px 20px 30px;
+    overflow: hidden;
+    box-shadow: 4px 4px 15px 0px rgba(180, 212, 212, 0.59);
+    background-color: rgba(255, 255, 255, 0.3);
+    .caption {
+      display: flex;
+      justify-content: space-around;
+      font-size: 14px;
+      color: rgba(102, 102, 102, 1);
+      .system_text {
+        padding: 0 6px 5px;
+        border-bottom: 2px solid rgb(255, 255, 255);
+      }
+      .text_active {
+        color: rgba(35, 139, 232, 1);
+        padding: 0 6px 5px;
+        border-bottom: 2px solid rgba(35, 139, 232, 1);
+      }
+    }
+    .text_active {
+      font-size: 14px;
+      color: rgba(35, 139, 232, 1);
+    }
+    .balance {
+      font-size: 20px;
+      font-weight: bold;
+      color: #000;
+      margin: 12px 0 16px;
+    }
+    .universal {
+      display: flex;
+      // align-items: center;
+      flex-direction: column;
+      // justify-content: space-between;
+      font-size: 14px;
+      color: rgba(102, 102, 102, 1);
+      margin-top: 12px;
+      .li {
+        display: flex;
+        flex-direction: column;
+        line-height: 150%;
+        letter-spacing: 1px;
+        font-size: 13px;
+        padding-top: 6px;
+        // align-items: center;
+        .li_amount {
+          // font-weight: bold;
+          color: #000;
+          margin-top: 8px;
+        }
+      }
+    }
+    .slider {
+      margin: 10px 0 18px;
+      display: flex;
+      align-items: center;
+      input {
+        border: 0;
+        background-color: #f1f1f1;
+        width: 100%;
+        padding: 10px 10px;
+        border-radius: 6px;
+        font-size: 14px;
+        color: #000;
+      }
+      textarea {
+        border: 0;
+        background-color: #f1f1f1;
+        width: 100%;
+        padding: 10px 10px;
+        border-radius: 6px;
+        font-size: 14px;
+        color: #000;
+        resize: none;
+      }
+      .danwei {
+        font-size: 13px;
+        padding-left: 6px;
+      }
+    }
+    .hint {
+      font-size: 12px;
+      color: rgba(102, 102, 102, 1);
+      padding-left: 6px;
+    }
+  }
+  .button {
+    display: flex;
+    justify-content: center;
+    .submit_button {
+      color: rgba(#fff, 0.95);
+      background: #2f46d4;
+      border: 0;
+      border-radius: 12px;
+      padding: 12px 0;
+      width: 100%;
+      margin-top: 30px;
+      letter-spacing: 1.5px;
+    }
+  }
+}
+.bind_box {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: 50px 0;
+  .address_field {
+    padding-top: 16px;
+  }
+}
+.all {
+  font-size: 10px;
+  white-space: nowrap;
+  padding: 6px;
+  border: 1px solid #238be8;
+  border-radius: 10px;
+  margin-left: 10px;
+}
+</style>

+ 5 - 1
src/views/mine/assets.vue

@@ -22,6 +22,10 @@
           <img src="@/assets/images/wallet/icon2.png" alt="" class="icon" />
           <span>SMH管理</span>
         </div>
+        <div class="balance_li" @click="navigation('arManage', '')">
+          <img src="@/assets/images/wallet/icon2.png" alt="" class="icon" />
+          <span>AR管理</span>
+        </div>
       </div>
       <!-- <div class="balance_box">
         <div class="balance_li" @click="navigation('etcWithdraw', '')">
@@ -183,7 +187,7 @@ export default {
       display: flex;
       align-items: center;
       flex-direction: column;
-      width: 48%;
+      width: 32%;
       font-size: 14px;
       border-radius: 16px;
       padding: 16px 0;

+ 2 - 2
src/views/mine/smhExchange.vue

@@ -28,11 +28,11 @@
             <input type="text" v-model="address" :disabled="disable" placeholder="请输入提币地址" />
           </div> -->
           <div class="li">
-            <span>手续费:{{ dataObj.smh_ratio * 100 || 0 }}%</span>
+            <span>手续费:{{ dataObj.smh_exchange_ratio * 100 || 0 }}%</span>
           </div>
           <div class="li">
             <span>{{
-              `预计兑换: ${Math.floor(exchangeAmount * dataObj.smh_price * (1 - dataObj.smh_ratio * 1) * 100) / 100 || 0}U(1SMH = ${Math.floor(dataObj.smh_price * 100) / 100 || 0}U)`
+              `预计兑换: ${Math.floor(exchangeAmount * dataObj.smh_price * (1 - dataObj.smh_exchange_ratio * 1) * 100) / 100 || 0}U(1SMH = ${Math.floor(dataObj.smh_price * 100) / 100 || 0}U)`
             }}</span>
           </div>
         </div>

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels