OSDN Git Service

complete vote function
authorZhiting Lin <zlin035@uottawa.ca>
Mon, 26 Aug 2019 07:32:01 +0000 (15:32 +0800)
committerZhiting Lin <zlin035@uottawa.ca>
Mon, 26 Aug 2019 07:32:01 +0000 (15:32 +0800)
14 files changed:
src/assets/language/cn.js
src/assets/language/en.js
src/assets/style.css
src/router.js
src/store/actions.js
src/store/constants.js
src/store/mutations.js
src/store/store.js
src/utils/GenericTools.js
src/views/home.vue
src/views/vote/listCancel.vue [new file with mode: 0644]
src/views/vote/listVote.vue
src/views/vote/veto.vue [new file with mode: 0644]
src/views/vote/vote.vue

index 9134a3f..265d611 100644 (file)
@@ -66,6 +66,11 @@ const cn = {
     vote:'投票',
     votes:'票数'
   },
+  listCancel:{
+    voted:'已投票',
+    cancel:'可取消',
+    selectVote:'选择节点'
+  },
   vote:{
     selectNode:'选择节点'
   },
index 1ff233e..a070f53 100644 (file)
@@ -66,6 +66,11 @@ const en = {
     vote:'Vote',
     votes:'Votes'
   },
+  listCancel:{
+    voted:'Voted',
+    cancel:'Cancel',
+    selectVote:'Choose to vote'
+  },
   vote:{
     selectNode:'Select Node'
   },
index 0cc3d6c..81b580d 100644 (file)
@@ -89,6 +89,10 @@ a {
   float: right;
 }
 
+.text-aglin-right {
+  text-aglin: right;
+}
+
 h1,
 h2 {
   font-weight: 500;
index b93e25f..8dd7240 100644 (file)
@@ -26,6 +26,14 @@ const routers = [
         }
       },
       {
+        path: '/listCancel',
+        name: 'listCancel',
+        meta: { title: '选择节点' },
+        component: resolve => {
+          require(['@/views/vote/listCancel.vue'], resolve)
+        }
+      },
+      {
         path: '/vote',
         name: 'vote',
         meta: { title: '投票' },
@@ -34,6 +42,14 @@ const routers = [
         }
       },
       {
+        path: '/veto',
+        name: 'veto',
+        meta: { title: '取消投票' },
+        component: resolve => {
+          require(['@/views/vote/veto.vue'], resolve)
+        }
+      },
+      {
         path: '/crossChain',
         name: 'cross-chain',
         meta: { title: '跨链' },
index 1a250cf..54a2237 100644 (file)
@@ -6,8 +6,11 @@ import account from "../models/account";
 
 export const actions = {
     [Actions.SET_BYTOM]:({commit}, bytom) => commit(Actions.SET_BYTOM, bytom),
+    [Actions.SET_LIST_VOTE]:({commit}, listVote) => commit(Actions.SET_LIST_VOTE, listVote),
+    [Actions.SET_SELECTED_VOTE]:({commit}, selectVote) => commit(Actions.SET_SELECTED_VOTE, selectVote),
 
-    [Actions.LOAD_BYTOM]:({dispatch}) => {
+
+  [Actions.LOAD_BYTOM]:({dispatch}) => {
         return new Promise((resolve, reject) => {
             InternalMessage.signal(InternalMessageTypes.LOAD).send().then(_bytom => {
                 dispatch(Actions.SET_BYTOM, Bytom.fromJson(_bytom));
index 1e1ea93..5d765d8 100644 (file)
@@ -7,6 +7,8 @@ export const CREATE_NEW_BYTOM = 'createNewBytom';
 export const CREATE_NEW_BYTOM_ACCOUNT = 'createNewAccount';
 export const IMPORT_BYTOM = 'importBytom';
 export const SET_AUTO_LOCK = 'setAutoLock';
+export const SET_LIST_VOTE = 'setListVote';
+export const SET_SELECTED_VOTE = 'setSelectVote';
 export const LOCK = 'lock';
 export const DESTROY = 'destroy';
 
index a1d28d8..f2365f7 100644 (file)
@@ -8,6 +8,9 @@ export const mutations = {
     [Mutations.PUSH_ALERT_RESULT]:(state, alertResult) => state.alertResult = alertResult,
     [Mutations.CLEAR_ALERT_RESULT]:(state) => state.alertResult = null,
     [Mutations.PUSH_PROMPT]:(state, prompt) => state.prompt = prompt,
-    // [Mutations.SET_AUTO_LOCK]:(state, inactivityInterval) =>
+    [Mutations.SET_LIST_VOTE]:(state, listVote) => state.listVote = listVote,
+    [Mutations.SET_SELECTED_VOTE]:(state, selectVote) => state.selectVote = selectVote,
+
+  // [Mutations.SET_AUTO_LOCK]:(state, inactivityInterval) =>
     //     state.bytom.settings.inactivityInterval = TimingHelpers.minutes(inactivityInterval),
 };
index 249871f..a1d41fe 100644 (file)
@@ -13,6 +13,8 @@ const state = {
     alertResult:null,
 
     prompt:null,
+    listVote:[],
+    selectVote: null,
 };
 
 const getters = {
index a56b67e..38eda48 100644 (file)
@@ -6,4 +6,4 @@ export const strippedHost = () => {
     if(host.indexOf('www.') === 0) host = host.replace('www.', '');
 
     return host;
-};
\ No newline at end of file
+};
index 476ee19..c6be665 100644 (file)
@@ -8,7 +8,7 @@
     display:flex;
 }
 .topbar .topbar-left {
-    width: 115px;
+    width: 85px;
     overflow: hidden;
     text-overflow: ellipsis;
     white-space: nowrap;
@@ -79,6 +79,7 @@
     height: 48px;
     line-height: 23px;
     font-size: 16px;
+    padding: 12px 10px;
 }
 
 .btn-received {
     width: 90%;
 }
 
-.list-item .value {
-    float: right;
-    margin-top: 13px;
-}
 .account-address {
     cursor: pointer;
 }
                 </div>
                 <div class="topbar-middle bg-secondary">
                     <select :value="netType" @change="netTypeToggle">
-                        <option value="bytom">{{ $t('main.bytom') }}</option>
-                        <option value="vapor">{{ $t('main.vapor') }}</option>
+                        <option value="bytom">{{ $t('main.bytom') }} {{net}}</option>
+                        <option value="vapor">{{ $t('main.vapor') }} {{net}}</option>
                     </select>
                 </div>
             </div>
                       <vue-scroll @handle-scroll="handleScroll">
                       <ul class="list">
                           <li class="list-item" v-for="(transaction, index) in transactions" :key="index" @click="$router.push({name: 'transfer-info', params: {transaction: transaction, address: currentAccount.address}})">
-                              <div class="value">{{transaction.direct}} {{transaction.val.toFixed(2)}} BTM</div>
+                              <div class="float-right text-aglin-right">
+                                <div class="value">{{transaction.direct}} {{transaction.val.toFixed(2)}} BTM</div>
+                                <div v-if="transaction.type == 'vote'" class="addr color-grey">{{ $t('listVote.vote')}} {{transaction.vAmount}}</div>
+                                <div v-else-if="transaction.type == 'veto'" class="addr color-grey">{{ $t('listVote.cancelVote')}}  {{transaction.vAmount}}</div>
+                                <div v-else-if="transaction.type == 'crossChain'" class="addr color-grey">{{ $t('crossChain.title')}}</div>
+                              </div>
                               <div>
                                   <div v-if="transaction.hasOwnProperty('block_timestamp')">
                                     {{transaction.submission_timestamp | moment}}
@@ -278,6 +280,7 @@ import { BTM } from "@/utils/constants";
 import { mapActions, mapGetters, mapState } from 'vuex'
 import * as Actions from '@/store/constants';
 import _ from 'lodash';
+import { Number as Num } from "@/utils/Number"
 
 
 const EnterActive = 'animated faster fadeInLeft';
@@ -438,6 +441,7 @@ export default {
             }
         },
         refreshBalance: function (guid) {
+          if(guid){
             account.balance(guid)
               .then((obj)=>{
                 const balances = obj.balances
@@ -474,6 +478,7 @@ export default {
               .catch(error => {
                 console.log(error);
             });
+          }
         },
         refreshTransactions: function (guid, address, start, limit) {
             return new Promise((resolve, reject) => {
@@ -498,8 +503,22 @@ export default {
             const balanceObject = transaction.balances
               .filter(b => b.asset === assetID);
 
-            if(balanceObject.length ===1 ){
+            const filterInput = _.find(transaction.inputs, function(o) { return o.type =='veto'; })
+
+            if(filterInput){
+              transaction.type = 'veto'
+              const inAmount = _.sumBy((transaction.inputs.filter(i => i.type ==='veto')), 'amount')
+              const outAmount = _.sumBy((transaction.outputs.filter(i => i.type ==='vote')), 'amount')
+              transaction.vAmount =  Num.formatNue(inAmount-outAmount)
+            }else if(_.find(transaction.outputs, function(o) { return o.type =='vote'; })){
+              const outAmount = _.sumBy((transaction.outputs.filter(i => i.type ==='vote')), 'amount')
+              transaction.vAmount =  Num.formatNue(outAmount)
+              transaction.type = 'vote'
+            }else if(_.find(transaction.outputs, function(o) { return o.type =='crosschain_output'; })){
+              transaction.type = 'crossChain'
+            }
 
+            if(balanceObject.length ===1 ){
                 const inputAddresses = transaction.inputs
                   .filter(input => input.asset === assetID && input.address !== this.address)
                   .map(input => input.address)
diff --git a/src/views/vote/listCancel.vue b/src/views/vote/listCancel.vue
new file mode 100644 (file)
index 0000000..af87859
--- /dev/null
@@ -0,0 +1,191 @@
+<style lang="" scoped>
+.header {
+  display: flex;
+}
+.header p{
+  text-align: center;
+  width: 270px;
+  padding-top: 17px;
+}
+.my-vote {
+  height: 115px;
+    padding: 20px;
+  display: flex;
+  text-align: center;
+  flex-direction: column;
+  font-size:14px;
+}
+
+.my-vote .vote-number{
+  font-size: 28px;
+  padding: 15px 0;
+}
+
+.vote-list {
+    border-radius:4px;
+    height: 505px;
+    overflow: scroll;
+    padding: 20px 0px;
+}
+
+.votes{
+  width: 100%;
+}
+
+.vote-item> td{
+  padding: 12px 15px;
+  border-bottom: 1px solid #F0F0F0;
+  cursor: pointer;
+}
+  .vote-item img{
+    height: 36px;
+    width: 36px;
+    border:1px solid #E0E0E0;
+    opacity:1;
+    border-radius:4px;
+    margin-right: 15px;
+  }
+  .vote-item .vote-title{
+    font-size: 14px;
+  }
+  .vote-item .vote-number{
+    font-size: 12px;
+    color: #8A8A8A;
+  }
+
+  .vote-title{
+    font-size: 14px;
+    line-height: 36px;
+    vertical-align: middle;
+    align-items: center;
+    display: flex;
+  }
+
+</style>
+
+<template>
+    <div class="warp-chlid bg-gray">
+      <section class="header bg-header">
+        <i class="iconfont icon-back" @click="close"></i>
+        <p>{{ $t('listCancel.selectVote') }}</p>
+      </section>
+
+        <section class="vote-container  bg-white">
+          <div class="vote-list">
+            <table class="list votes">
+              <tr class="vote-item" v-for="(vote, index) in filteredList" :key="index"  @click="openVeto(vote)">
+                  <td >
+                    <div class="vote-title" >
+                      <img  :src="vote.logo" alt="">
+                      <div v-if="net === 'mainnet'">
+                        <a :href="`https://vapor.blockmeta.com/node/${vote.pub_key}`" target="_blank">
+                          {{vote.name}}
+                        </a>
+                      </div>
+                      <div v-else>
+                        {{vote.name}}
+                      </div>
+                    </div>
+                    <div class="vote-number">{{$t('listCancel.voted')}} {{formatNue(vote.total)}}</div>
+                  </td>
+                <td>
+                  <div class="vote-title">{{formatNue(vote.total-vote.locked)}} </div>
+                   <div class="vote-number"> {{$t('listCancel.cancel')}} </div>
+                </td>
+              </tr>
+            </table>
+          </div>
+        </section>
+    </div>
+</template>
+
+<script>
+import query from "@/models/query";
+import { BTM } from "@/utils/constants";
+import Number from "@/utils/Number"
+import { mapActions, mapGetters, mapState } from 'vuex'
+import _ from 'lodash';
+import * as Actions from '@/store/constants';
+
+
+export default {
+    components: {
+    },
+    data() {
+        return {
+          votes:[],
+          totalVote:0,
+          search:''
+        };
+    },
+    computed: {
+        unit() {
+            return this.assets[this.transaction.asset];
+        },
+        voteRole(){
+            return function (roleNum) {
+              switch (roleNum){
+                case 0:
+                  return 'vote-role bp';
+                case 1:
+                  return 'vote-role stanbybp';
+                case 2:
+                  return 'vote-role otherbp';
+                default:
+                  return 'vote-role otherbp';
+              }
+            }
+        },
+      myVote() {
+        let vote
+        const votes = this.currentAccount.votes
+        if(votes && votes.length >0 ){
+          vote = _.sumBy(votes,'total')
+        }
+        return (vote != null && vote != 0) ? Number.formatNue(vote) : '0.00'
+      },
+      filteredList() {
+        return this.votes.filter(post => {
+          return post.name.toLowerCase().includes(this.search.toLowerCase())
+        })
+      },
+      ...mapState([
+        'bytom',
+        'listVote'
+      ]),
+      ...mapGetters([
+        'currentAccount',
+        'accountList',
+        'net'
+      ])
+    },
+    watch: {
+
+    },
+    methods: {
+        close: function () {
+            this.$router.go(-1)
+            },
+        formatNue: function (nue) {
+          return Number.formatNue(nue);
+        },
+        formatFraction: function (upper, lower) {
+          return Number.fractionalNum(upper, lower);
+        },
+        openVeto: function(veto){
+          this[Actions.SET_SELECTED_VOTE](veto);
+          this.$router.push({name: 'veto'});
+        },
+        ...mapActions([
+          Actions.SET_SELECTED_VOTE,
+        ])
+    },
+    mounted() {
+      const originVotes = this.currentAccount.votes
+      const allVotes = this.listVote;
+      this.votes = _.map(originVotes, function(obj) {
+        return _.assign(obj, _.find(allVotes, {pub_key: obj.vote}));
+      });
+    }
+};
+</script>
index ef4a7e6..41b5f1c 100644 (file)
 
         <section class="vote-container  bg-white">
           <div>
-            <button>{{ $t('listVote.voteRecord')}}</button>
             <button>{{ $t('listVote.voteRules')}}</button>
-            <button>{{ $t('listVote.cancelVote')}}</button>
+            <router-link :to="{name: 'listCancel'}">
+              {{ $t('listVote.cancelVote')}}
+            </router-link>
           </div>
           <div class="vote-label color-black">
             <div>
                     <div class="vote-number">{{$t('listVote.votes')}} {{formatNue(vote.vote_num)}} ({{formatFraction(vote.vote_num, totalVote)}})</div>
                   </td>
                 <td>
-                  <router-link :to="{name: 'vote', params: { vote: vote }}">
+                  <button @click="openVote(vote)">
                     {{$t('listVote.vote')}}
-                  </router-link>
+                  </button>
                 </td>
               </tr>
             </table>
@@ -160,6 +161,7 @@ import query from "@/models/query";
 import { BTM } from "@/utils/constants";
 import Number from "@/utils/Number"
 import { mapActions, mapGetters, mapState } from 'vuex'
+import * as Actions from '@/store/constants';
 import _ from 'lodash';
 
 export default {
@@ -167,7 +169,6 @@ export default {
     },
     data() {
         return {
-          votes:[],
           totalVote:0,
           search:''
         };
@@ -199,17 +200,18 @@ export default {
         return (vote != null && vote != 0) ? Number.formatNue(vote) : '0.00'
       },
       filteredList() {
-        return this.votes.filter(post => {
+        return this.listVote.filter(post => {
           return post.name.toLowerCase().includes(this.search.toLowerCase())
         })
       },
       ...mapState([
-        'bytom'
+        'bytom',
+        'listVote'
       ]),
       ...mapGetters([
         'currentAccount',
         'accountList',
-        'net'
+        'net',
       ])
     },
     watch: {
@@ -224,16 +226,25 @@ export default {
         },
         formatFraction: function (upper, lower) {
           return Number.fractionalNum(upper, lower);
-        }
+        },
+        openVote: function(vote){
+          this[Actions.SET_SELECTED_VOTE](vote);
+          this.$router.push({name: 'vote'});
+        },
+        ...mapActions([
+          Actions.SET_LIST_VOTE,
+          Actions.SET_SELECTED_VOTE,
+        ])
     },
     mounted() {
       query.chainStatus().then(resp => {
         if(resp){
           this.totalVote = resp.total_vote_num;
-          this.votes =  resp.consensus_nodes.map( (item, index) => {
+          const votes =  resp.consensus_nodes.map( (item, index) => {
             item.rank = index+1;
             return item
           });
+          this[Actions.SET_LIST_VOTE](votes)
         }
       });
     }
diff --git a/src/views/vote/veto.vue b/src/views/vote/veto.vue
new file mode 100644 (file)
index 0000000..4f30acd
--- /dev/null
@@ -0,0 +1,189 @@
+<style lang="" scoped>
+.header {
+  display: flex;
+}
+.header p{
+  text-align: center;
+  width: 270px;
+  padding-top: 17px;
+}
+
+.transferType input[type=radio] {
+  position: absolute;
+  visibility: hidden;
+}
+
+.transferType input[type="radio"]:checked+label{
+  color:white;
+  background-color: #333333;
+}
+
+.form-container{
+  margin: 20px;
+}
+.form {
+    margin-bottom: 20px;
+    padding: 10px 15px;
+    border-radius:4px;
+}
+.form-container .btn{
+    height: 48px;
+    bottom: 20px;
+    position: absolute;
+    width: 320px;
+}
+.vote-title{
+  font-size: 14px;
+  color: #000;
+  vertical-align: middle;
+  align-items: center;
+  display: flex;
+}
+.vote-title img{
+  height: 36px;
+  width: 36px;
+  border:1px solid #E0E0E0;
+  opacity:1;
+  border-radius:4px;
+  margin-right: 15px;
+}
+</style>
+
+<template>
+    <div class="warp-chlid bg-gray">
+        <section class="header bg-header">
+            <i class="iconfont icon-back" @click="close"></i>
+            <p>{{ $t('listVote.cancelVote') }}</p>
+        </section>
+
+        <section class="form-container">
+          <div class="form bg-white">
+            <div v-if="selectVote !== null" class="form-item">
+              <label class="form-item-label">{{ $t('vote.selectNode') }}</label>
+              <div class="form-item-content" >
+                <div class="vote-title" >
+                  <img  :src="selectVote.logo" alt="">
+                  <div>
+                    {{selectVote.name}}
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div class="form bg-white">
+
+              <div class="form-item">
+                  <label class="form-item-label">
+                    {{ $t('transfer.quantity') }}
+
+                    <small class="float-right" style="margin-right: 8px;">{{ transaction.cost||0 }} CNY</small>
+                  </label>
+                  <div class="form-item-content" style=" display: flex;">
+                      <input type="number" v-model="transaction.amount" :placeholder="bytomBalance">
+                      <span class="color-grey" style="width: 40px; font-size: 15px;position: absolute;right: 0;">{{unit}}</span>
+                  </div>
+              </div>
+          </div>
+          <a class="btn btn-primary" @click="send">{{ $t('transfer.send') }}</a>
+        </section>
+    </div>
+</template>
+
+<script>
+import transaction from "@/models/transaction";
+import getLang from "@/assets/language/sdk";
+import Confirm from "../sendTransaction/transferConfirm";
+import { BTM } from "@/utils/constants";
+import { mapGetters, mapState } from 'vuex'
+import { Number as Num } from "@/utils/Number"
+
+
+export default {
+    components: {
+        Confirm
+    },
+    data() {
+        return {
+            show: false,
+            accountBalance: 0.00,
+            unit: 'BTM',
+            fee: this.$t("transfer.feeType"),
+            feeTypeOptions: [this.$t("transfer.feeType")],
+            transaction: {
+                amount: "",
+                to:'',
+                confirmations: 1
+            }
+        };
+    },
+    computed: {
+      bytomBalance: function () {
+        const vote = this.selectVote
+        let vetoAmount
+        if(vote && vote.total > vote.locked ){
+          vetoAmount = Num.formatNue(vote.total-vote.locked)
+        }
+
+          return `Vapor${this.$t("crossChain.amountPlaceHolder")}${(vetoAmount != null && vetoAmount != 0) ? vetoAmount : '0.00'}`
+      },
+      ...mapState([
+        'bytom',
+        'selectVote'
+      ]),
+      ...mapGetters([
+        'currentAccount',
+        'accountList',
+        'net',
+        'netType'
+      ])
+    },
+    watch: {
+        "transaction.amount": function (newAmount) {
+            transaction.asset(BTM).then(ret => {
+                this.transaction.cost = Number(ret.cny_price * newAmount).toFixed(2);
+            });
+        },
+        account: function (newAccount) {
+            this.guid = newAccount.guid;
+        }
+    },
+    methods: {
+        close: function () {
+            this.$router.go(-1)
+            this.transaction.vote = "";
+            this.transaction.amount = "";
+        },
+        send: function () {
+            if (this.transaction.amount <= 0) {
+                this.$dialog.show({
+                    body: this.$t("transfer.noneBTM")
+                });
+                return;
+            }
+
+            let loader = this.$loading.show({
+                // Optional parameters
+                container: null,
+                canCancel: true,
+                onCancel: this.onCancel
+            });
+
+            const vote = this.selectVote.pub_key
+            this.transaction.to = vote
+            transaction.buildVeto(this.currentAccount.guid, vote,  this.transaction.amount*100000000, this.transaction.confirmations).then(result => {
+                loader.hide();
+                console.log(result)
+                this.transaction.fee = Number(result.fee / 100000000);
+                this.$router.push({ name: 'transfer-confirm', params: { account: this.currentAccount, transaction: this.transaction, rawData: result} })
+            }).catch(error => {
+                loader.hide();
+                this.$dialog.show({
+                    body: getLang(error.message)
+                });
+            });
+
+        }
+    }, mounted() {
+    }
+};
+</script>
index 07e1067..05f2e51 100644 (file)
     <div class="warp-chlid bg-gray">
         <section class="header bg-header">
             <i class="iconfont icon-back" @click="close"></i>
-            <p>{{ $t('crossChain.title') }}</p>
+            <p>{{ $t('listVote.vote') }}</p>
         </section>
 
         <section class="form-container">
           <div class="form bg-white">
-            <div v-if="vote !== null" class="form-item">
+            <div v-if="selectVote !== null" class="form-item">
               <label class="form-item-label">{{ $t('vote.selectNode') }}</label>
               <div class="form-item-content" >
                 <div class="vote-title" >
-                  <img  :src="vote.logo" alt="">
+                  <img  :src="selectVote.logo" alt="">
                   <div>
-                    {{vote.name}}
+                    {{selectVote.name}}
                   </div>
                 </div>
               </div>
@@ -107,7 +107,6 @@ export default {
             unit: 'BTM',
             fee: this.$t("transfer.feeType"),
             feeTypeOptions: [this.$t("transfer.feeType")],
-            vote:null,
             transaction: {
                 amount: "",
                 to:'',
@@ -127,7 +126,8 @@ export default {
           return `Vapor${this.$t("crossChain.amountPlaceHolder")}${(balance != null && balance != 0) ? balance : '0.00'}`
       },
       ...mapState([
-        'bytom'
+        'bytom',
+        'selectVote'
       ]),
       ...mapGetters([
         'currentAccount',
@@ -138,7 +138,7 @@ export default {
     },
     watch: {
         "transaction.amount": function (newAmount) {
-            transaction.asset(this.transaction.asset).then(ret => {
+            transaction.asset(BTM).then(ret => {
                 this.transaction.cost = Number(ret.cny_price * newAmount).toFixed(2);
             });
         },
@@ -167,7 +167,7 @@ export default {
                 onCancel: this.onCancel
             });
 
-            const vote = this.vote.pub_key
+            const vote = this.selectVote.pub_key
             this.transaction.to = vote
             transaction.buildVote(this.currentAccount.guid, vote,  this.transaction.amount*100000000, this.transaction.confirmations).then(result => {
                 loader.hide();
@@ -182,7 +182,6 @@ export default {
 
         }
     }, mounted() {
-        this.vote = this.$route.params.vote
     }
 };
 </script>