OSDN Git Service

722ebb3642d92d18c655ebb28e301cca01d762ac
[bytom/Byone.git] / src / views / home.vue
1 <style lang="" scoped>
2 .warp {
3     z-index: 1;
4 }
5
6 .topbar {
7     font-size: 19px;
8     display:flex;
9 }
10 .topbar .topbar-left {
11     width: 87px;
12     overflow: hidden;
13     text-overflow: ellipsis;
14     white-space: nowrap;
15     padding-top: 20px;
16     padding-left: 20px;
17 }
18 .topbar-left .btn-menu {
19     float: left;
20     margin-right: 8px;
21 }
22 .topbar-left .btn-menu i {
23     font-size: 100%;
24 }
25 .alias {
26     height: 25px;
27     font-size: 16px;
28     line-height: 28px;
29 }
30
31 .topbar .topbar-middle {
32     margin-top: 20px;
33     margin-right: 20px;
34     border: 2px solid #fff;
35     border-radius: 18px;
36     padding: 0 20px;
37     font: 12px system-ui;
38     text-align: center;
39     display: flex;
40     align-items: center;
41 }
42
43 .content {
44     margin-top: 25px;
45     text-align: center;
46     padding: 0 30px 10px;
47 }
48 .content .token-icon {
49     display: inline-flex;
50     height: 40px;
51     width: 40px;
52     padding: 8px;
53     margin: 8px;
54 }
55 .content .amount {
56     padding-bottom: 10px;
57 }
58 .content .token-amount {
59     font-size: 32px;
60     line-height: 45px;
61 }
62 .token-amount .asset {
63     font-size: 18px;
64     margin-left: 2px;
65 }
66 .qrcode {
67     margin-left: 5px;
68     vertical-align: middle;
69     cursor: pointer;
70 }
71
72 .btn-send-transfer {
73     display: flex;
74     align-items: center;
75     justify-content: center;
76 }
77 .btn-send-transfer .btn {
78     width: 160px;
79     height: 48px;
80     line-height: 23px;
81     font-size: 16px;
82 }
83
84 .btn-received {
85     background: #0DBF37;
86     border-radius:4px 0px 0px 0px;
87 }
88 .btn-received:active,
89 .btn-received:hover,.btn-received:focus {
90     background: #05A02A;
91 }
92
93 .btn-transfer {
94     background: #035BD4;
95     border-radius:0px 4px 0px 0px;
96 }
97 .btn-transfer:active,
98 .btn-transfer:hover,.btn-transfer:focus {
99   background: #044BAF;
100 }
101
102 .transaction-title h3 {
103     font-size: 16px;
104     font-weight: inherit;
105     padding: 10px 0 10px 20px;
106 }
107 .transactions {
108   font-size: 15px;
109   height: 340px;
110   overflow: auto;
111 }
112 .list-item {
113     position: relative;
114     display: block;
115     padding: 10px 20px;
116 }
117
118 .list-item:after {
119     content:"";
120     background: #e0e0e0;
121     position: absolute;
122     bottom: 0;
123     left: 20px;
124     height: 1px;
125     width: 90%;
126 }
127
128 .list-item .value {
129     float: right;
130     margin-top: 13px;
131 }
132 .account-address {
133     cursor: pointer;
134 }
135 .btn-creation {
136     display: block;
137     width: 310px;
138     height: 48px;
139     margin: auto;
140     padding: 15px 0;
141     position: absolute;
142     bottom: 20px;
143     left: 20px;
144 }
145
146 .time, .value{
147   font-weight: 500;
148   font-size: 16px;
149 }
150 .addr{
151   font-size: 12px;
152 }
153 .no-tx-img{
154   width: 100px;
155   height: 100px;
156 }
157 .no-record{
158   display: block;
159 }
160
161   .btn-send-transfer .iconfont{
162     margin-right: 4px;
163   }
164
165 </style>
166
167 <template>
168     <div class="warp">
169         <section class="bg-image">
170             <div class="topbar">
171                 <div class="topbar-left">
172                     <a class="btn-menu" @click="openMenu">
173                         <i class="iconfont icon-menu"></i>
174                     </a>
175                 </div>
176                 <div class="topbar-middle bg-secondary">
177                     <select v-model="network" @change="networkToggle">
178                         <option value="mainnet">{{ $t('main.mainNet') }}</option>
179                         <option value="testnet">{{ $t('main.testNet') }}</option>
180                     </select>
181                 </div>
182             </div>
183             <div class="content">
184                 <div v-if="currentAccount.address!=undefined" class="amount color-white">
185                     <span class="alias color-grey">{{currentAccount.alias}}</span>
186                     <div class="token-amount">
187                         {{accountBalance}}
188                         <span class="asset">BTM</span>
189                     </div>
190                 </div>
191                 <div v-else>
192                   <p style="width: 250px; margin: 45px auto; text-align: center;">{{ $t('main.noAccount') }}</p>
193
194                 </div>
195             </div>
196             <div class="btn-send-transfer">
197                 <a v-if="currentAccount.address!=undefined" class="btn btn-primary btn-received" @click="showQrcode">
198                   <i class="iconfont icon-receive"></i>
199                   {{ $t('main.receive') }}
200                 </a>
201                 <a v-if="currentAccount.address!=undefined" class="btn btn-primary btn-transfer" @click="transferOpen">
202                   <i class="iconfont icon-send"></i>
203                   {{ $t('main.send') }}
204                 </a>
205             </div>
206         </section>
207
208             <section class="transaction-title">
209                 <h3 class="bg-gray color-grey">{{ $t('main.record') }}</h3>
210             </section>
211             <section class="transactions">
212                  <div v-if="currentAccount.address!=undefined">
213                   <div v-if="transactions.length != 0">
214                       <vue-scroll @handle-scroll="handleScroll">
215                       <ul class="list">
216                           <li class="list-item" v-for="(transaction, index) in transactions" :key="index" @click="$router.push({name: 'transfer-info', params: {transaction: transaction, address: currentAccount.address}})">
217                               <div class="value">{{transaction.direct}} {{transaction.val.toFixed(2)}} BTM</div>
218                               <div>
219                                   <div v-if="transaction.hasOwnProperty('block_timestamp')">
220                                     {{transaction.submission_timestamp | moment}}
221                                   </div>
222                                   <div v-else>
223                                     {{ $t('main.unconfirmed') }}
224                                   </div>
225                                   <div class="addr color-grey">{{transaction.address}}</div>
226                               </div>
227                           </li>
228                       </ul>
229                   </vue-scroll>
230                   </div>
231                       <div v-else>
232                           <div class="bg-emptytx"></div>
233                           <div>
234                               <span class="color-lightgrey center-text no-record">{{$t('main.noRecord')}}</span>
235                           </div>
236                       </div>
237                   </div>
238                   <div v-else>
239                       <router-link :to="{name: 'menu-account-creation'}">
240                           <div class="bg-emptytx"></div>
241                           <div>
242                             <span class="color-lightgrey center-text no-record">{{$t('main.noRecord')}}</span>
243                           </div>
244                           <a class="btn btn-primary btn-creation">{{ $t('main.create') }}</a>
245                       </router-link>
246                   </div>
247             </section>
248
249         <!-- child page -->
250         <div class="mask" v-show="maskShow"></div>
251         <transition :enter-active-class="enterActive" :leave-active-class="leaveActive">
252             <router-view></router-view>
253         </transition>
254
255     </div>
256 </template>
257
258 <script>
259 import address from "@/utils/address";
260 import account from "@/models/account";
261 import transaction from "@/models/transaction";
262 import { BTM } from "@/utils/constants";
263
264 const EnterActive = 'animated faster fadeInLeft';
265 const LeaveActive = 'animated faster fadeOutLeft';
266 export default {
267     name: "",
268     data() {
269         return {
270             network: "mainnet",
271             accounts: [],
272             currentAccount: {},
273             transactions: [],
274             maskShow: false,
275             start: 0,
276             limit: 10,
277             enterActive: EnterActive,
278             leaveActive: LeaveActive,
279         };
280     },
281     watch: {
282         '$route'(to, from) {
283             if (to.name.startsWith('menu')) {
284                 this.maskShow = true
285             } else if (from.name.startsWith('menu')) {
286                 this.maskShow = false
287             }
288
289             //account toggle by the list from menu
290             if (to.name == 'home' && to.params.selectedAccount != undefined) {
291                 this.currentAccount = to.params.selectedAccount
292                 this.refreshAccounts();
293             }
294
295             // remove transition for some page
296             this.enterActive = EnterActive
297             this.leaveActive = LeaveActive
298             if (to.name == 'transfer-confirm' || from.name == 'transfer-confirm') {
299                 this.enterActive = ''
300                 this.leaveActive = ''
301             }
302         },
303         currentAccount(newVal, oldVal) {
304             if (newVal.guid == undefined){
305               localStorage.currentAccount = {}
306               return;
307             }
308             localStorage.currentAccount = JSON.stringify(newVal);
309
310             this.refreshTransactions(newVal.guid, newVal.address).then(transactions => {
311                 this.transactions = transactions
312             });
313         },
314         'currentAccount.guid'(guid) {
315             if (guid == undefined) return;
316
317             this.refreshBalance(guid);
318         }
319     },
320     computed: {
321         shortAddress: function () {
322             return address.short(this.currentAccount.address)
323         },
324         accountBalance: function () {
325             return (this.currentAccount.balance != null && this.currentAccount.balance != 0) ? this.currentAccount.balance : '0.00'
326         }
327     },
328     methods: {
329         setupRefreshTimer() {
330             setInterval(() => {
331                 this.refreshBalance(this.currentAccount.guid)
332             }, 10000)
333         },
334         setupNetwork() {
335             this.network = localStorage.bytomNet;
336             account.setupNet(this.network);
337         },
338         networkToggle: function (val) {
339             localStorage.bytomNet = this.network;
340             account.setupNet(this.network);
341             this.currentAccount = {}
342             this.refreshAccounts();
343         },
344         showQrcode: function () {
345           this.$router.push({ name: 'received', params: { address: this.currentAccount.address } })
346         },
347         openMenu: function () {
348             this.$router.push({ name: 'menu', params: { accounts: this.accounts, selected: this.currentAccount } })
349         },
350         transferOpen: function () {
351             this.$router.push({ name: 'transfer', params: { account: this.currentAccount } })
352         },
353         handleScroll(vertical, horizontal, nativeEvent) {
354             if (vertical.process == 0) {
355                 this.start = 0;
356                 this.refreshTransactions(this.currentAccount.guid, this.currentAccount.address).then(transactions => {
357                     this.transactions = transactions
358                 });
359                 return;
360             }
361
362             if (vertical.process == 1) {
363                 this.start += this.limit;
364                 this.refreshTransactions(this.currentAccount.guid, this.currentAccount.address, this.start, this.limit).then(transactions => {
365                     transactions.forEach(transaction => {
366                         this.transactions.push(transaction);
367                     });
368                 });
369             }
370         },
371         refreshAccounts: function () {
372           account.list().then(accounts => {
373                 this.accounts = accounts;
374                 if (accounts.length == 0) {
375                     return;
376                 }
377
378                 if (this.currentAccount.guid == undefined) {
379                     this.currentAccount = accounts[0];
380                 }
381             })
382         },
383         refreshBalance: function (guid) {
384             account.balance(guid).then(balances => {
385                 let balance = 0
386                 if(balances.length >0 ){
387                   const balanceObject = balances.filter(b => b.asset === BTM)[0]
388                   balance = balanceObject.balance/Math.pow(10,balanceObject.decimals)
389                 }
390                 this.currentAccount.balance = balance;
391                 this.currentAccount = Object.assign({}, this.currentAccount);
392             }).catch(error => {
393                 console.log(error);
394             });
395         },
396         refreshTransactions: function (guid, address, start, limit) {
397             return new Promise((resolve, reject) => {
398                 transaction.list(guid, address, start, limit).then(transactions => {
399                     if (transactions == null) {
400                         return;
401                     }
402
403                     const formattedTx = this.transactionsFormat(transactions);
404                     resolve(formattedTx)
405                 }).catch(error => {
406                     console.log(error);
407                     reject(error)
408                 });
409             })
410         },
411         transactionsFormat: function (transactions) {
412           const formattedTransactions = []
413           const assetID = BTM
414
415           transactions.forEach(transaction => {
416             const balanceObject = transaction.balances
417               .filter(b => b.asset === assetID);
418
419             if(balanceObject.length ===1 ){
420
421                 const inputAddresses = transaction.inputs
422                   .filter(input => input.asset === assetID && input.address !== this.currentAccount.address)
423                   .map(input => input.address)
424
425                 const outputAddresses = transaction.outputs
426                   .filter(output => output.asset === assetID && output.address !== this.currentAccount.address)
427                   .map(output => output.address)
428
429
430                 const val  = assetID===BTM ? Number(balanceObject[0].amount)/ 100000000 : Number(balanceObject[0].amount);
431
432                 if (val > 0) {
433                     transaction.direct = "+";
434                     transaction.address = address.short(inputAddresses.pop());
435                 } else {
436                     transaction.direct = "-";
437                     transaction.address = address.short(outputAddresses.pop());
438                 }
439
440                 transaction.val = Math.abs(val);
441                 transaction.fee = transaction.fee / 100000000;
442
443                 formattedTransactions.push(transaction);
444               }
445             });
446           return formattedTransactions;
447         },
448     },
449     mounted() {
450         if(localStorage.currentAccount !== undefined){
451           this.currentAccount = JSON.parse(localStorage.currentAccount);
452         }
453         this.setupNetwork();
454         this.refreshAccounts();
455         this.setupRefreshTimer();
456     }
457 };
458 </script>