Commit 8e93cc58 authored by chenqikuai's avatar chenqikuai

新增区块链浏览器

parent fdde44a9
VUE_APP_BACKEND = https://public.zhaobi.tech/web/api VUE_APP_BACKEND = https://public.zhaobi.tech/web/api
//VUE_APP_BACKEND = http://47.114.159.142:9055 //VUE_APP_BACKEND = http://47.114.159.142:9055
\ No newline at end of file
# 所属链
VUE_APP_PLATFORM=YCC
# 主代币
VUE_APP_BASECOIN=YCC
# 主代币图标
VUE_APP_BASECOIN_URL='/YCC.png'
VUE_APP_DEFAULT_LANG='en'
\ No newline at end of file
module.exports = { module.exports = {
root: true, root: true,
env: { env: {
node: true node: true,
}, },
'extends': [ extends: [
'plugin:vue/essential', "plugin:vue/essential",
'eslint:recommended', "eslint:recommended",
'@vue/typescript/recommended' "@vue/typescript/recommended",
], ],
parserOptions: { parserOptions: {
ecmaVersion: 2020 ecmaVersion: 2020,
}, },
rules: { rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', "no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off' "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
} "@typescript-eslint/explicit-module-boundary-types": "off",
} },
};
.DS_Store .DS_Store
node_modules node_modules
/dist /dist
/ycc-website
# local env files # local env files
......
module.exports = { module.exports = {
presets: [ presets: [
'@vue/cli-plugin-babel/preset' '@vue/cli-plugin-babel/preset',
["@babel/preset-env", { "modules": false }]
],
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
] ]
} }
rm -rf ycc-website
cp -r dist ycc-website
tar -czf ycc-website.tar ycc-website
scp ycc-website.tar root@121.40.18.70:/usr/share/nginx/html/ycc-website.tar
rm -rf ycc-website.tar
ssh root@121.40.18.70 'cd /usr/share/nginx/html && rm -rf ycc-website && tar -xzf ycc-website.tar && rm -rf ycc-website.tar'
echo '👉 http://121.40.18.70:4749/'
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -3,28 +3,42 @@ ...@@ -3,28 +3,42 @@
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"scripts": { "scripts": {
"serve": "vue-cli-service serve", "dev": "vue-cli-service serve",
"build": "vue-cli-service build", "build": "vue-cli-service build --report",
"deploy": "npm run build && bash deploy.sh",
"lint": "vue-cli-service lint" "lint": "vue-cli-service lint"
}, },
"dependencies": { "dependencies": {
"@33cn/chain33-transaction-parser": "^1.1.4",
"@tailwindcss/line-clamp": "^0.2.0", "@tailwindcss/line-clamp": "^0.2.0",
"@tailwindcss/postcss7-compat": "^2.0.4", "@tailwindcss/postcss7-compat": "^2.0.4",
"ant-design-vue": "^1.7.5", "ant-design-vue": "^1.7.5",
"autoprefixer": "^9", "autoprefixer": "^9",
"clipboard": "^2.0.8",
"compression-webpack-plugin": "^5.0.0", "compression-webpack-plugin": "^5.0.0",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"echarts": "^5.3.0",
"element-ui": "^2.15.6",
"moment": "^2.29.1",
"moment-locales-webpack-plugin": "^1.2.0",
"postcss": "^7", "postcss": "^7",
"protobufjs": "6.10.1",
"qrcode": "^1.5.0",
"register-service-worker": "^1.7.2", "register-service-worker": "^1.7.2",
"swiper": "^6.6.1", "swiper": "^6.6.1",
"tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.1.0", "tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.1.0",
"terser-webpack-plugin": "^5.1.2", "terser-webpack-plugin": "^5.1.2",
"vue": "^2.6.11", "vue": "^2.6.11",
"vue-count-to": "^1.0.13",
"vue-i18n": "^8.24.4", "vue-i18n": "^8.24.4",
"vue-router": "^3.2.0", "vue-router": "^3.2.0",
"vuex": "^3.4.0" "vue-typed-mixins": "^0.2.0",
"vuex": "^3.4.0",
"ycc-api": "^0.0.5"
}, },
"devDependencies": { "devDependencies": {
"@babel/preset-env": "^7.16.11",
"@types/qrcode": "^1.4.2",
"@typescript-eslint/eslint-plugin": "^4.18.0", "@typescript-eslint/eslint-plugin": "^4.18.0",
"@typescript-eslint/parser": "^4.18.0", "@typescript-eslint/parser": "^4.18.0",
"@vue/cli-plugin-babel": "~4.5.0", "@vue/cli-plugin-babel": "~4.5.0",
...@@ -34,11 +48,12 @@ ...@@ -34,11 +48,12 @@
"@vue/cli-plugin-vuex": "~4.5.0", "@vue/cli-plugin-vuex": "~4.5.0",
"@vue/cli-service": "~4.5.0", "@vue/cli-service": "~4.5.0",
"@vue/eslint-config-typescript": "^7.0.0", "@vue/eslint-config-typescript": "^7.0.0",
"babel-plugin-component": "^1.1.1",
"eslint": "^6.7.2", "eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2", "eslint-plugin-vue": "^6.2.2",
"typescript": "~4.1.5",
"vue-template-compiler": "^2.6.11",
"sass": "^1.26.5", "sass": "^1.26.5",
"sass-loader": "^8.0.2" "sass-loader": "^7.1.0",
"typescript": "~4.1.5",
"vue-template-compiler": "^2.6.11"
} }
} }
<template> <template>
<div id="app"> <div id="app">
<router-view/> <router-view />
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from 'vue'
export default Vue.extend({ export default Vue.extend({
name: 'Home', name: 'Home',
})
});
</script> </script>
<style>
.el-table--striped .el-table__body td.el-table__cell {
background: #fafbfc;
}
.el-table--striped .el-table__body tr.el-table__row--striped:hover > td {
background: rgba(37, 69, 203, 0.04) !important;
}
.el-table--striped .el-table__body tr.el-table__row--striped td.el-table__cell {
background: white;
}
.c-consensusNodeTable {
border-bottom: 10px solid #fafbfc !important;
}
.c-consensusNodeTable .el-table::before {
height: 0px;
}
.c-consensusNodeTable td.el-table__cell {
border-bottom: 10px solid #fafbfc !important;
border-top: 10px solid #fafbfc !important;
}
.el-table .el-table__header thead tr {
height: 70px;
}
.el-table .el-table__body-wrapper .el-table__row {
height: 60px;
}
.el-table td.el-table__cell,
.el-table th.el-table__cell.is-leaf {
border-bottom: 0 !important;
}
table .has-gutter {
color: #7c88ad;
}
.ant-message {
z-index: 4000 !important;
}
.my-title {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #7c88ad;
}
.my-block-height {
font-size: 32px;
font-family: DINAlternate-Bold, DINAlternate;
font-weight: bold;
color: #2545cb;
}
.my-benifit {
font-size: 24px;
font-family: DINAlternate-Bold, DINAlternate;
font-weight: bold;
color: #22356c;
}
.my-content1 {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #1f3470;
}
.slide-in-enter-active {
transition: all 0.3s ease;
}
.slide-in-leave-active {
transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);
}
.slide-in-enter, .slide-fade-leave-to
/* .slide-in-leave-active for below version 2.1.8 */ {
transform: translateX(10px);
opacity: 0;
}
</style>
This diff is collapsed.
...@@ -3,9 +3,9 @@ import VueI18n from "vue-i18n"; ...@@ -3,9 +3,9 @@ import VueI18n from "vue-i18n";
Vue.use(VueI18n); Vue.use(VueI18n);
export const i18n = new VueI18n({ export const i18n = new VueI18n({
locale: 'zh', locale: "zh",
messages: { messages: {
'zh': require('./zh.ts'), zh: require("./zh.ts"),
'en': require('./en.ts') en: require("./en.ts"),
} },
}) });
\ No newline at end of file
This diff is collapsed.
<template>
<div class="charts" ref="charts"></div>
</template>
<script lang="ts">
import Vue from 'vue'
import * as echarts from 'echarts/core'
import { LineChart, LineSeriesOption } from 'echarts/charts'
import { TooltipComponent, GridComponent } from 'echarts/components'
import { CanvasRenderer } from 'echarts/renderers'
import { numOfOnChainTx } from '@/service/api'
import moment from 'moment'
import { nFormatter } from '@/utils/common'
type ECOption = echarts.ComposeOption<LineSeriesOption>
echarts.use([TooltipComponent, GridComponent, LineChart, CanvasRenderer])
export default Vue.extend({
props: {
scale: String,
grid: Object,
},
data() {
return {
xData: [],
seriesData: [],
}
},
methods: {
generateD1() {
const list = []
for (let i = 0; i < 7; ++i) {
const m = moment().startOf('days').add(-i, 'days')
list.push(m)
}
return list.map((i) => {
return {
start: i.unix(),
format: i.format('YYYY.MM.DD'),
end: i.endOf('days').unix(),
}
})
},
generateW1() {
const list = []
for (let i = 0; i < 7; ++i) {
const m = moment()
.hour(0)
.minute(0)
.second(0)
.add(-i * 7, 'days')
list.push(m)
}
return list.map((i) => {
return {
start: moment(i).add(-1, 'weeks').unix(),
end: moment(i).unix(),
format: `${moment(i).add(-1, 'weeks').format('MMMDD')} - ${moment(
i,
).format('MMMDD')}`,
}
})
},
generateM1() {
const list = []
for (let i = 0; i < 7; ++i) {
const m = moment().startOf('month').add(-i, 'month')
list.push(m)
}
return list.map((i) => {
return {
start: moment(i).unix(),
end: moment(i).endOf('month').unix(),
format: `${moment(i).format('MMM')}`,
}
})
},
generateY1() {
const list = []
for (let i = 0; i < 7; ++i) {
const m = moment().hour(0).minute(0).second(0).add(-i, 'year')
list.push(m)
}
return list.map((i) => {
return {
start: i.startOf('year').unix(),
end: i.endOf('year').unix(),
format: `${i.format('YYYY')}`,
}
})
},
generate() {
switch (this.scale) {
case 'D1':
return this.generateD1()
case 'W1':
return this.generateW1()
case 'M1':
return this.generateM1()
case 'Y1':
return this.generateY1()
}
},
draw() {
// 接下来的使用就跟之前一样,初始化图表,设置配置项
// filters: ['D1', 'W1', 'M1', 'Y1'],
const times = this.generate()
times &&
numOfOnChainTx(times).then((ret) => {
if (ret.error == null) {
this.xData = ret.result
var myChart = echarts.init(this.$refs.charts as HTMLElement)
myChart.setOption({
tooltip: {
trigger: 'axis',
},
xAxis: {
type: 'category',
axisLabel: {
textStyle: {
color: '#7c88ad',
},
},
axisTick: {
show: false,
},
data: times
?.map((i) => {
return i.format
})
.reverse(),
},
yAxis: {
type: 'value',
axisLabel: {
formatter: (item: number) => {
return nFormatter(item)
},
textStyle: {
color: '#7c88ad',
},
},
},
series: [
{
type: 'line',
data: this.xData.map((i: any) => i || 0).reverse(),
areaStyle: {
color: 'red',
normal: {
// 颜色渐变函数 前四个参数分别表示四个位置依次为左、下、右、上
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: '#2545CB', // 0% 处的颜色
},
{
offset: 0.6,
color: '#9FAEE9', // 40% 处的颜色
},
{
offset: 1,
color: 'white', // 100% 处的颜色
},
]), //背景渐变色
lineStyle: {
// 系列级个性化折线样式
type: 'solid',
color: '#2545CB', //折线的颜色
},
},
},
smooth: true,
showSymbol: false,
itemStyle: {},
},
],
grid: { ...this.grid },
} as ECOption)
}
})
},
},
mounted() {
this.draw()
},
watch: {
scale(v) {
this.draw()
},
'$route.query.lang'() {
this.draw()
},
},
})
</script>
<style lang="scss" scoped>
.charts {
width: 100%;
}
</style>
<template>
<div class="charts" ref="charts"></div>
</template>
<script lang="ts">
import * as echarts from 'echarts/core'
import { LineSeriesOption, LineChart } from 'echarts/charts'
import { TooltipComponent, GridComponent } from 'echarts/components'
import { CanvasRenderer } from 'echarts/renderers'
import { getAccountRecords } from '@/service/api'
import moment from 'moment'
type ECOption = echarts.ComposeOption<LineSeriesOption>
echarts.use([TooltipComponent, GridComponent, LineChart, CanvasRenderer])
import chartsMixin from '@/mixin/componentsMixin/charts'
import VueTypedMixins from 'vue-typed-mixins'
import { nFormatter } from '@/utils/common'
export default VueTypedMixins(chartsMixin).extend({
props: {
scale: String,
grid: Object,
},
data() {
return {
xData: [],
seriesData: [],
}
},
methods: {
generate() {
switch (this.scale) {
case 'D1':
return this.generateD1()
case 'W1':
return this.generateW1()
case 'M1':
return this.generateM1()
case 'M6':
return this.generateM6()
case 'Y1':
return this.generateY1()
}
},
draw() {
const times = this.generate()
times &&
getAccountRecords(
this.$route.query.address as string,
times,
'ycc',
).then((ret) => {
if (ret.error == null) {
this.xData = ret.result
const myChart = echarts.init(this.$refs.charts as HTMLElement)
myChart.setOption({
tooltip: {
trigger: 'axis',
},
xAxis: {
type: 'category',
axisLabel: {
textStyle: {
color: '#7c88ad',
},
},
axisTick: {
show: false,
},
data: times
?.map((i) => {
return moment.unix(i).format('YYYY.MM.DD')
})
.reverse(),
},
yAxis: {
type: 'value',
axisLabel: {
formatter: (item: number) => {
return nFormatter(item)
},
textStyle: {
color: '#7c88ad',
},
},
},
series: [
{
data: this.xData
// eslint-disable-next-line @typescript-eslint/no-explicit-any
.map((i: any) => (i && i[0] && i[0].balance) || 0)
.map((i) => i / 1e8)
.reverse(),
type: 'line',
areaStyle: {
normal: {
// 颜色渐变函数 前四个参数分别表示四个位置依次为左、下、右、上
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: '#2545CB', // 0% 处的颜色
},
{
offset: 0.6,
color: '#9FAEE9', // 40% 处的颜色
},
{
offset: 1,
color: 'white', // 100% 处的颜色
},
]), //背景渐变色
lineStyle: {
// 系列级个性化折线样式
type: 'solid',
color: '#2545CB', //折线的颜色
},
},
},
smooth: true,
showSymbol: false,
itemStyle: {},
},
],
grid: this.grid,
} as ECOption)
}
})
},
},
mounted() {
this.draw()
},
watch: {
'$route.query.address'() {
this.draw()
},
scale() {
this.draw()
},
},
})
</script>
<style lang="scss" scoped>
.charts {
width: 100%;
}
</style>
...@@ -12,6 +12,11 @@ ...@@ -12,6 +12,11 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import locale from 'element-ui/lib/locale'
import enLocale from "element-ui/lib/locale/lang/en";
import zhLocale from "element-ui/lib/locale/lang/zh-CN";
import moment from 'moment';
import Vue from 'vue' import Vue from 'vue'
export default Vue.extend({ export default Vue.extend({
props: { props: {
...@@ -24,34 +29,22 @@ export default Vue.extend({ ...@@ -24,34 +29,22 @@ export default Vue.extend({
}, },
methods: { methods: {
selectLanguage(v: string) { selectLanguage(v: string) {
if(v === 'zh-CN'){
locale.use(zhLocale)
}else {
locale.use(enLocale)
}
this.$emit('selectIcon', v) this.$emit('selectIcon', v)
this.$emit('hidden', true) this.$emit('hidden', true)
window.sessionStorage.setItem('language', v) window.sessionStorage.setItem('language', v)
this.$i18n.locale = v === 'zh-CN' ? 'zh' : 'en' this.$i18n.locale = v === 'zh-CN' ? 'zh' : 'en'
console.log({...this.$route.query, lang: v}) document.title = `${this.$t('lang.YUANLIAN')}YCC——${this.$t(
'lang.title',
)}`
moment.locale(v === 'zh-CN' ? 'zh-cn' : 'en')
this.$router.replace({ path: this.$route.path, query: { ...this.$route.query, lang: v }}) this.$router.replace({ path: this.$route.path, query: { ...this.$route.query, lang: v }})
} }
}, },
created() {
// const _b = document.body || document.documentElement
// _b.addEventListener('click', (e) => {
// if (!this.show) return
// for (let item of e.path) {
// try {
// if (item.getAttribute('class').indexOf('i-select-item') <= -1) {
// this.$emit('hidden', true)
// }
// } catch(e) {
// throw Error(e)
// }
// }
// })
},
watch: {
// $route() {
// }
}
}) })
</script> </script>
......
<template>
<div>
<div
class="c-block-desc-top"
:style="{
backgroundImage: `url(${blockCardDescBg})`,
}"
>
<div class="flex items-end justify-between">
<img :src="blockIcon" class="blockIcon" alt="" />
</div>
<div class="flex justify-between mt-1">
<div class="text-text-color text-xs">
{{ $t('lang.txDetail.height') }}
</div>
<div>
<span class="text-text-color text-xs">
{{ $t('lang.block.blockReward') }}
</span>
<span class="text-footer-color text-sm font-bold">
{{ height | filterBlockReward }}
</span>
</div>
</div>
<div class="flex justify-between items-end mb-6" style="margin-top: 3px;">
<div class="text-footer-color font-bold text-3xl">
{{ height }}
</div>
<div class="mb-1">
<span class="text-text-color text-xs">
{{ $t('lang.block.txCount') }}
</span>
<span class="text-footer-color text-sm font-bold">
{{ txCount }}
</span>
</div>
</div>
<div class="flex mb-5">
<div class="text-text-color text-sm lableLeft">
{{ $t('lang.block.timestamp') }}
</div>
<div class="text-darkBlue text-sm">
{{ blockTime | formatTime }}
</div>
</div>
<div class="flex mb-5">
<div class="text-text-color text-sm lableLeft">
{{ $t('lang.block.hash') }}
</div>
<div class="text-darkBlue text-sm flex items-center">
<div>
{{ hash | filterHash(10) }}
</div>
<m-copy-btn class="ml-2" :copyTxt="hash"></m-copy-btn>
</div>
</div>
<div class="flex mb-5">
<div class="text-text-color text-sm lableLeft">
{{ $t('lang.block.merkelgen') }}
</div>
<div class="text-darkBlue text-sm flex items-center">
<div>
{{ merkelgen | filterHash(10) }}
</div>
<m-copy-btn class="ml-2" :copyTxt="merkelgen"></m-copy-btn>
</div>
</div>
<div class="flex">
<div class="text-text-color text-sm lableLeft">
{{ $t('lang.block.stateHash') }}
</div>
<div class="text-darkBlue text-sm flex items-center">
<div>
{{ stateHash | filterHash(10) }}
</div>
<m-copy-btn class="ml-2" :copyTxt="stateHash"></m-copy-btn>
</div>
</div>
</div>
<div class="c-block-desc-bottom flex justify-between">
<div
class="relativeBlock relativeBlock-last text-center flex-grow"
:style="{
backgroundImage: `url(${lastBlockBg})`,
}"
>
<div class="mt-5 text-text-color text-xs" style="margin-bottom: 3px;">
{{ $t('lang.block.lastBlock') }}
</div>
<div class="text-footer-color text-base font-bold">
<router-link
:to="{
path: '/blockDetail',
query: {
height: lastBlockHeight,
},
}"
v-if="
typeof lastBlockHeight === 'number' && lastBlockHeight !== NaN
"
>
{{ lastBlockHeight }}
</router-link>
<div v-else>
{{ $t('lang.block.no') }}
</div>
</div>
</div>
<div style="width: 15px;"></div>
<div
class="relativeBlock relativeBlock-next text-center flex-grow"
:style="{
backgroundImage: `url(${nextBlockBg})`,
}"
>
<div class="mt-5 text-text-color text-xs" style="margin-bottom: 3px;">
{{ $t('lang.block.nextBlock') }}
</div>
<div class="text-footer-color text-base font-bold">
<router-link
:to="{
path: '/blockDetail',
query: {
height: nextBlockHeight,
},
}"
v-if="
typeof nextBlockHeight === 'number' && nextBlockHeight !== NaN
"
>
{{ nextBlockHeight }}
</router-link>
<div v-else>
{{ $t('lang.block.no') }}
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
import blockCardDescBg from '@/assets/images/blockChainBrowser/blockDetail/block-card-desc-bg.png'
import blockIcon from '@/assets/images/blockChainBrowser/blockDetail/block.png'
import mCopyBtn from './m-copyBtn.vue'
import lastBlockBg from '@/assets/images/blockChainBrowser/blockDetail/lastBlockBg.png'
import nextBlockBg from '@/assets/images/blockChainBrowser/blockDetail/nextBlockBg.png'
export default Vue.extend({
components: { mCopyBtn },
props: {
loading: Boolean,
hash: String,
merkelgen: String,
stateHash: String,
blockTime: Number,
txCount: Number,
height: [Number, String],
lastBlockHeight: Number,
nextBlockHeight: Number,
},
data() {
return {
blockCardDescBg,
blockIcon,
lastBlockBg,
nextBlockBg,
}
},
})
</script>
<style lang="scss" scoped>
.c-block-desc-top {
height: 330px;
background: #ffffff;
box-shadow: 0px 2px 15px 0px rgba(31, 52, 112, 0.06);
border-radius: 4px;
background-position: 39px;
background-size: contain;
padding: 15px 15px;
.blockIcon {
width: 52px;
height: 52px;
}
.lableLeft {
width: 100px;
}
}
.c-block-desc-bottom {
margin-top: 15px;
.relativeBlock {
width: 160px;
height: 80px;
background: #ffffff;
box-shadow: 0px 1px 8px 0px rgba(31, 52, 112, 0.06);
border-radius: 2px;
background-size: 107px 80px;
background-repeat: no-repeat;
}
.relativeBlock-last {
background-position: left;
}
.relativeBlock-next {
background-position: right;
}
}
</style>
<template>
<div class="blockItem bg-white flex pr-3.5">
<div class="txNumBox text-center flex-shrink-0">
<div
class="text-footer-color text-base font-bold"
style="margin-top: 7px;"
>
{{ txCount }}
</div>
<div class="text-xs font-bold text-footer-color-light">
{{ txCount === 1 ? $t('lang.block.txCount_single') : $t('lang.block.txCount') }}
</div>
</div>
<div class="msgBox flex-shrink-0 flex-grow mt-3.5 ml-2">
<div class="flex justify-between items-center w-full">
<div class="text-darkBlue font-bold text-sm">
<router-link
:to="{
path: '/blockDetail',
query: {
height: height,
},
}"
>
{{ height }}
</router-link>
</div>
<div class="text-text-color text-xs">
{{ blockTime | formatTime }}
</div>
</div>
<div>
<span class="text-text-color text-xs">
{{ $t('lang.block.packingAddress') }}:
</span>
<span class="text-footer-color">
<router-link
:to="{
path: '/address',
query: {
address: packagingAddress,
},
}"
>
{{ packagingAddress | filterHash(12) }}
</router-link>
</span>
</div>
<div>
<span class="text-text-color text-xs">
{{ $t('lang.block.blockReward') }}
</span>
<span class="text-black text-xs">
{{ height | filterBlockReward }}
</span>
</div>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
props: {
txCount: Number,
height: Number,
blockTime: Number,
packagingAddress: String,
},
})
</script>
<style lang="scss" scoped>
.blockItem {
height: 90px;
.txNumBox {
margin-top: 18px;
width: 62px;
height: 54px;
background: rgba(37, 69, 203, 0.1);
border-radius: 2px;
margin-left: 15px;
}
border-bottom: 1px solid #f5f5ff;
}
.blockItem:last-of-type {
border-bottom: none;
}
</style>
<template>
<div class="m-blue-intro">
<img :src="txt" alt="" />
<div class="txt mt-2.5 text-lightBlue">{{ $t('lang.blockChain') }}</div>
<div class="txt text-lightBlue">
{{ $t('lang.browser') }}
</div>
</div>
</template>
<script lang="ts">
import VueTypedMixins from 'vue-typed-mixins'
import txt from '@/assets/images/blockChainBrowser/home/yccText.png'
export default VueTypedMixins().extend({
data() {
return {
txt,
}
},
})
</script>
<style scoped lang="scss">
.m-blue-intro {
width: 256px;
height: 290px;
background: #2545cb;
img {
width: 107px;
height: 36px;
margin-top: 95px;
margin-left: 129px;
}
.txt {
font-size: 18px;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
line-height: 25px;
margin-left: 129px;
letter-spacing: 1px;
}
}
</style>
<template>
<div class="c-perf py-2">
<div class="h-full">
<div
v-for="(item, i) in list"
:key="i"
class="h-1/4 pt-2.5"
style="margin-left: 10px;"
>
<div class="text-text-color text-xs" style="margin-bottom: 2px;">
{{ item.name }}
</div>
<div class="text-title-color text-sm font-bold">
{{ item.value }}
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { filterNum } from '@/utils/utils'
import Vue from 'vue'
export default Vue.extend({
props: {
speed: Number,
tps: Number,
txNumber: Number,
addressNumber: Number,
},
computed: {
list(): { name: string; value: string | number }[] {
return [
{
name: this.$t('lang.chainPerf.speed') as string,
value: this.speed + 's',
},
{
name: this.$t('lang.chainPerf.tps') as string,
value: this.tps,
},
{
name: this.$t('lang.chainPerf.txNumber') as string,
value: filterNum(this.txNumber),
},
{
name: this.$t('lang.chainPerf.addressNumber') as string,
value: filterNum(this.addressNumber),
},
]
},
},
})
</script>
<style lang="scss" scoped>
.c-perf {
height: 240px;
background: #ffffff;
box-shadow: 0px 1px 8px 0px rgba(31, 52, 112, 0.06);
border-radius: 2px;
}
</style>
<template>
<div class="c-chain-price flex flex-col">
<div
class="top w-full"
:style="{
backgroundImage: `url(${bg})`,
}"
>
<img :src="yccIcon" alt="" class="yccIcon" />
<div class="text-white font-bold text-xl mt-1">
{{ price }}{{ $t('lang.price.dollar') }}
</div>
<div
class="updown text-my-red font-bold text-xs flex items-center justify-center"
>
{{ quoteChange }}
</div>
<div class="text-xs text-white mt-6">
{{ $t('lang.price.realTimeQuotes') }}
</div>
<div class="text-xs text-white mt-1">
{{ $t('lang.price._24hourVolatility') }}
</div>
</div>
<div class="bottom text-center flex items-center w-full justify-center flex-grow">
<div>
<div class="text-text-color text-xs">
{{ $t('lang.price.marketValueInDollars') }}
</div>
<div class="text-footer-color font-bold">
{{ marketValue | filterNum }}
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
import bg from '@/assets/images/blockChainBrowser/home/beautiful-rect.png'
import yccIcon from '@/assets/images/blockChainBrowser/home/ycc-icon.png'
export default Vue.extend({
props: {
price: String,
quoteChange: String,
marketValue: Number,
},
data() {
return {
bg,
yccIcon,
}
},
})
</script>
<style lang="scss" scoped>
.c-chain-price {
width: 175px;
height: 240px;
background: #ffffff;
box-shadow: 0px 1px 8px 0px rgba(31, 52, 112, 0.06);
border-radius: 2px;
.top {
width: 175px;
height: 175px;
background-repeat: no-repeat;
background-size: cover;
padding-top: 17px;
padding-left: 15px;
.yccIcon {
width: 26px;
height: 26px;
}
.updown {
width: 50px;
height: 20px;
background: #ffffff;
border-radius: 2px;
}
}
}
</style>
<template>
<div class="card">
<div
class="item flex items-center"
v-for="(item, index) in msgList"
:key="index"
>
<img :src="item.icon" style="width: 26px; height: 26px;" alt="" />
<div>
<div class="text-text-color font-normal text-xs">
{{ item.title }}
</div>
<div class="text-title-color text-base font-bold">
{{ item.number | filterNum}}
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import Vue, { PropType } from 'vue'
export default Vue.extend({
props: {
msgList: Array as PropType<
{
icon: string
title: string
number: number
}[]
>,
},
})
</script>
<style scoped>
.card {
width: 200px;
height: 250px;
background: #ffffff;
box-shadow: 0px 7px 20px 0px rgba(31, 52, 112, 0.14);
border-radius: 20px;
padding-top: 15px;
}
.item {
height: 55px;
padding-left: 15px;
}
.item img {
margin-right: 13px;
}
</style>
<template>
<div class="c-search flex items-center justify-between">
<input
type="text"
class="outline-none w-full mx-3"
v-model="searchValue"
:placeholder="placeholder"
/>
<div
class="btn-search flex-shrink-0"
@click="
!loading && searchResult(searchValue)
searchValue = ''
"
v-loading="loading"
>
<img
class="w-4 h-4"
style="margin-top: 11px; margin-left: 13px;"
src="@/assets/images/blockChainBrowser/home/search.png"
/>
</div>
</div>
</template>
<script lang="ts">
import VueTypedMixins from 'vue-typed-mixins'
import ChainSearchMixin from '@/mixin/componentsMixin/ChainSearch'
export default VueTypedMixins(ChainSearchMixin).extend({
data() {
return {
searchValue: '',
}
},
})
</script>
<style scoped>
.c-search {
height: 38px;
background: #ffffff;
border-radius: 25px;
border: 1px solid #dee1e6;
}
.btn-search {
width: 49px;
height: 38px;
background: #2545cb;
border-radius: 0px 25px 25px 0px;
}
</style>
<template>
<div class="consensus-node" style="background: #fafbfc;">
<div
class="box"
:style="{
backgroundColor:
type === 'package' ? 'rgba(248, 164, 87, 0.05)' : 'white',
}"
>
<div class="flex items-center justify-between" style="margin-top: 4px;">
<div class="text-darkBlue text-sm font-bold">
{{
type === 'package'
? $t('lang.block.packingNode')
: $t('lang.block.votingNode')
}}
</div>
<Count :time="time" class="text-text-color text-xs"></Count>
</div>
<div class="flex justify-between items-center" style="margin-top: 5px;">
<div>
<span class="text-text-color text-xs">
{{ $t('lang.block.consensusAddress') }}:
</span>
<span
class="text-text-color text-xs"
:class="[
type === 'package' ? ' text-orange' : ' text-footer-color',
]"
>
<router-link
:to="{
path: '/address',
query: {
address,
},
}"
>
{{ address | filterHash(6) }}
</router-link>
</span>
</div>
<div>
<span class="text-text-color text-xs">
{{ $t('lang.block.blockReward') }}:
</span>
<span class="font-bold text-darkBlue text-xs">
{{ reward | filterAmount }}YCC
</span>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import Vue, { PropType } from 'vue'
import Count from '../pc/BlockChainBrowser/Count.vue'
export default Vue.extend({
components: {
Count,
},
props: {
type: {
type: String as PropType<'package' | 'vote'>,
default: 'package',
},
height: [Number, String],
address: String,
reward: Number,
time: Number,
},
})
</script>
<style lang="scss" scoped>
.consensus-node {
.box {
padding: 10px;
margin: 5px;
height: 70px;
border-radius: 2px;
}
}
</style>
<template>
<div class="w-3 h-3 inline-block" :data-clipboard-text="copyTxt" ref="btn">
<img :src="copyIcon" class="w-full h-full" />
</div>
</template>
<script lang="ts">
import Vue from 'vue'
import copyIcon from '@/assets/images/blockChainBrowser/blockDetail/copy.png'
import Clipboard from 'clipboard'
import { message } from 'ant-design-vue'
export default Vue.extend({
props: {
copyTxt: [String, Number],
},
data() {
return {
copyIcon,
}
},
mounted() {
this.init()
},
methods: {
init() {
const clipboard = new Clipboard(this.$refs.btn as Element)
clipboard.on('success', (e) => {
message.success(this.$t('lang.components.copySuc') as string)
e.clearSelection()
})
clipboard.on('error', () => {
message.error(this.$t('lang.components.copyErr') as string)
})
},
},
})
</script>
...@@ -3,20 +3,20 @@ ...@@ -3,20 +3,20 @@
<h4 class="m-title w-full text-20px text-title-color text-center pt-4">{{ $t('lang.whatIs') }}</h4> <h4 class="m-title w-full text-20px text-title-color text-center pt-4">{{ $t('lang.whatIs') }}</h4>
<div class="m-explain-btn flex justify-between px-5"> <div class="m-explain-btn flex justify-between px-5">
<div class="e-btn flex items-center justify-center relative"> <div class="e-btn flex items-center justify-center relative">
<img class="cursor-pointer" :class="{'opacity-0': index === 1}" src="@/assets/images/h-explain/ex1.png" alt="" @click="handleChange(1)"> <img class="cursor-pointer" :class="{'opacity-0': index === 1}" src="@/assets/images/home/ex1.png" alt="" @click="handleChange(1)">
<img class="cursor-pointer absolute pointer-events-none" :class="{'opacity-0': index !== 1}" src="@/assets/images/h-explain/exa1.png" alt=""> <img class="cursor-pointer absolute pointer-events-none" :class="{'opacity-0': index !== 1}" src="@/assets/images/home/exa1.png" alt="">
</div> </div>
<div class="e-btn flex items-center justify-center relative"> <div class="e-btn flex items-center justify-center relative">
<img class="cursor-pointer" :class="{'opacity-0': index === 2}" src="@/assets/images/h-explain/ex2.png" alt="" @click="handleChange(2)"> <img class="cursor-pointer" :class="{'opacity-0': index === 2}" src="@/assets/images/home/ex2.png" alt="" @click="handleChange(2)">
<img class="cursor-pointer absolute pointer-events-none" :class="{'opacity-0': index !== 2}" src="@/assets/images/h-explain/exa2.png" alt=""> <img class="cursor-pointer absolute pointer-events-none" :class="{'opacity-0': index !== 2}" src="@/assets/images/home/exa2.png" alt="">
</div> </div>
<div class="e-btn flex items-center justify-center relative"> <div class="e-btn flex items-center justify-center relative">
<img class="cursor-pointer" :class="{'opacity-0': index === 3}" src="@/assets/images/h-explain/ex3.png" alt="" @click="handleChange(3)"> <img class="cursor-pointer" :class="{'opacity-0': index === 3}" src="@/assets/images/home/ex3.png" alt="" @click="handleChange(3)">
<img class="cursor-pointer absolute pointer-events-none" :class="{'opacity-0': index !== 3}" src="@/assets/images/h-explain/exa3.png" alt=""> <img class="cursor-pointer absolute pointer-events-none" :class="{'opacity-0': index !== 3}" src="@/assets/images/home/exa3.png" alt="">
</div> </div>
<div class="e-btn flex items-center justify-center relative"> <div class="e-btn flex items-center justify-center relative">
<img class="cursor-pointer" :class="{'opacity-0': index === 4}" src="@/assets/images/h-explain/ex4.png" alt="" @click="handleChange(4)"> <img class="cursor-pointer" :class="{'opacity-0': index === 4}" src="@/assets/images/home/ex4.png" alt="" @click="handleChange(4)">
<img class="cursor-pointer absolute pointer-events-none" :class="{'opacity-0': index !== 4}" src="@/assets/images/h-explain/exa4.png" alt=""> <img class="cursor-pointer absolute pointer-events-none" :class="{'opacity-0': index !== 4}" src="@/assets/images/home/exa4.png" alt="">
</div> </div>
</div> </div>
<div class="px-5" :class="enStyle ? 'explain_m_b' : 'explain_b'"> <div class="px-5" :class="enStyle ? 'explain_m_b' : 'explain_b'">
...@@ -44,13 +44,13 @@ export default Vue.extend({ ...@@ -44,13 +44,13 @@ export default Vue.extend({
handleChange(v: number) { handleChange(v: number) {
this.index = v this.index = v
if (this.timer) clearInterval(this.timer) if (this.timer) clearInterval(this.timer)
this.timer = setInterval(() => { this.timer = window.setInterval(() => {
this.index < 4 ? this.index++ : this.index = 1 this.index < 4 ? this.index++ : this.index = 1
}, 4000) }, 4000)
} }
}, },
created() { created() {
this.timer = setInterval(() => { this.timer = window.setInterval(() => {
this.index < 4 ? this.index++ : this.index = 1 this.index < 4 ? this.index++ : this.index = 1
}, 4000) }, 4000)
}, },
......
<template>
<div class="c-latestBlocks">
<div class="top flex items-center justify-between px-3.5">
<div class="text-darkBlue text-sm font-bold">
{{ $t('lang.chainMsg.latestBlock') }}
</div>
<div class="text-footer-color text-xs" @click="$router.push('/block')">
{{ $t('lang.viewMore') }}
</div>
</div>
<m-block-item
class="flex"
v-for="(item, i) in latestBlocks"
:key="i"
:blockTime="item.blockTime"
:height="item.height"
:packagingAddress="item.minerHash"
:txCount="item.txs && item.txs.length"
></m-block-item>
</div>
</template>
<script lang="ts">
import Vue, { PropType } from 'vue'
import mBlockItem from './m-blockItem.vue'
import { iBlockMsg } from 'ycc-api/dist/cmjs/service/home/types'
export default Vue.extend({
components: { mBlockItem },
props: {
latestBlocks: Array as PropType<iBlockMsg[]>,
},
})
</script>
<style lang="scss" scoped>
.c-latestBlocks {
.top {
height: 50px;
background: #ffffff;
border-radius: 2px;
}
}
</style>
<template>
<div class="c-latestBlocks">
<div class="top flex items-center justify-between px-3.5">
<div class="text-darkBlue text-sm font-bold">
{{ $t('lang.latestTx') }}
</div>
<div
class="text-footer-color text-xs"
@click="$router.push('/tradeList')"
>
{{ $t('lang.viewMore') }}
</div>
</div>
<m-tx-item
v-for="(n, i) in latestTxs"
:key="i"
:row="n"
:blockTime="n.time_block"
:amount="n.amount"
:txHash="n.hash"
:from="n.from"
:hideStatus="true"
:to="n.to"
></m-tx-item>
</div>
</template>
<script lang="ts">
import Vue, { PropType } from 'vue'
import mTxItem from './m-txItem.vue'
export default Vue.extend({
components: { mTxItem },
props: {
latestTxs: Array as PropType<any[]>,
},
})
</script>
<style lang="scss" scoped>
.c-latestBlocks {
.top {
height: 50px;
background: #ffffff;
border-radius: 2px;
}
}
</style>
<template>
<div class="m-page-container">
<div class="simple flex justify-end">
<el-pagination
background
small
@current-change="handleCurrentChange"
:current-page="currentPageNum"
:page-size="pageSize"
:page-sizes="[10, 20, 30]"
layout="prev,pager,next"
:total="total"
:pager-count="5"
></el-pagination>
</div>
<div class="detail flex mt-3.5 items-center justify-end" v-if="!simple">
<el-pagination
background
small
@current-change="handleCurrentChange"
:current-page="currentPageNum"
:page-size="pageSize"
layout="total,jumper"
:total="total"
:pager-count="5"
></el-pagination>
<div class="confirm">{{ $t('lang.page.confirm') }}</div>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
name: 'pages',
components: {},
data() {
return {
currentPageNum: this.currentPage,
firstPageBtnDisabled: true,
lastPageBtnDisabled: false,
}
},
props: {
currentPage: {
type: Number,
default: 1,
},
pageSize: {
type: Number,
default: 10,
},
total: {
type: Number,
default: 0,
},
simple: {
type: Boolean,
default: true,
},
},
watch: {
currentPage(newVal) {
this.currentPageNum = newVal
this.firstPageBtnDisabled = this.currentPageNum === 1 ? true : false
this.lastPageBtnDisabled =
this.currentPageNum === this.lastPageNum ? true : false
},
},
computed: {
lastPageNum(): number {
return Math.ceil(this.total / this.pageSize)
},
},
methods: {
handleCurrentChange(page: number) {
this.firstPageBtnDisabled = page === 1 ? true : false
this.lastPageBtnDisabled = page === this.lastPageNum ? true : false
this.currentPageNum = page
this.$emit('pageChange', page)
},
handleSizeChange(size: number) {
this.$emit('sizeChange', size)
},
},
})
</script>
<style lang="scss">
$blue: #dee1e6;
$white: #6368de;
.m-page-container {
.btn-prev,
.btn-next {
margin: 0 !important;
height: 30px !important;
min-width: 30px !important;
background: white !important;
border: 1px solid #dee1e6;
}
.btn-prev {
border-right: none;
}
.el-pagination {
.el-pager li:not(.disabled).active {
background-color: $blue;
color: #6368de;
}
.el-pager li {
background: white;
line-height: 30px;
text-align: center;
min-width: 30px !important;
height: 30px;
margin: 0 !important;
font-weight: 500;
font-size: 12px;
border: 1px solid #dee1e6;
border-right: none;
}
}
.confirm {
min-width: 58px;
height: 30px;
line-height: 30px;
background: #2545cb;
border-radius: 15px;
padding: 0 5px;
flex-shrink: 1;
margin-left: 10px;
display: inline-block;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ffffff;
text-align: center;
cursor: pointer;
}
.el-pagination {
padding: 0;
}
.el-pagination__jump {
margin-left: 0;
.el-input__inner {
font-size: 12px;
}
}
.el-pagination__sizes {
margin: 0;
.el-input {
width: 84px;
.el-input__inner {
height: 22px;
line-height: 22px;
font-size: 12px;
}
}
}
.el-pagination__total,
.el-pagination__jump {
margin: 0;
margin-left: 4px;
font-size: 12px;
font-family: PingFangSC;
font-weight: 400;
line-height: 30px !important;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #8093a7;
height: 30px !important;
}
.el-pagination__editor.el-input {
width: 65px;
height: 30px;
input {
width: 100%;
height: 100% !important;
}
}
.first-pager,
.last-pager {
background: #f4f4f5;
}
}
</style>
<template>
<div
class="c-title flex items-center pl-3.5 bg-white text-darkBlue font-bold text-sm"
>
<div
class="text-sm font-bold relative mr-7"
:class="[
tab.value === focusedTab ? ' text-footer-color' : ' text-text-color',
]"
@click="setFocusedTab(tab.value)"
v-for="(tab, i) in tabList"
:key="i"
>
{{ tab.name }}
<div
v-if="tab.value === focusedTab"
class="absolute -bottom-1 left-1/2 -translate-x-1/2 transform bg-footer-color"
style="width: 14px; height: 2px;"
></div>
</div>
</div>
</template>
<script lang="ts">
import Vue, { PropType } from 'vue'
export default Vue.extend({
props: {
focusedTab: String,
setFocusedTab: Function,
tabList: Array as PropType<
{
name: string
value: string
}[]
>,
},
})
</script>
<style lang="scss" scoped>
.c-title {
height: 50px;
}
</style>
<template>
<div class="c-title flex items-center pl-3.5 bg-white text-darkBlue font-bold text-sm">
{{ title }}
</div>
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
props: {
title: String,
},
})
</script>
<style lang="scss" scoped>
.c-title {
height: 50px;
}
</style>
<template>
<div
class="px-3.5 txItem flow-root relative"
:class="[txGroup ? 'bg-lightBlue2' : 'bg-white']"
>
<div class="leftLine" v-if="txGroup"></div>
<img
:src="txGroupIcon"
alt="txGroupIcon"
v-if="txGroup && txGroup === 'isGroupItem'"
class="w-5 h-5 txGroupIcon"
/>
<div class="flex justify-between items-center" style="margin-top: 14px;">
<div class="flex items-center">
<div class="text-text-color text-xs" style="margin-right: 3px;">
{{ $t('lang.trade.txAmount') }} :
</div>
<div class="text-darkBlue text-sm font-bold">
{{ row | TradeValue }}
</div>
</div>
<div class="text-xs text-text-color">
{{ blockTime | formatTime }}
</div>
</div>
<div
class="flex items-center justify-between"
style="margin-top: 3px; margin-bottom: 3px;"
>
<div class="flex items-center">
<div class="text-text-color text-xs" style="margin-right: 3px;">
{{ $t('lang.txDetail.txHash') }} :
</div>
<div
class="text-xs"
:class="[txGroup ? ' text-lightBlue' : 'text-footer-color']"
>
<router-link
:to="{
path: '/tradeHash',
query: {
hash: txHash,
},
}"
>
{{ txHash | filterHash }}
</router-link>
</div>
</div>
<TxStatus v-if="!hideStatus" size="small" :status="status" />
</div>
<div class="flex items-center justify-between">
<div>
<span class="text-text-color text-xs">
{{ $t('lang.trade.sender') }} :
</span>
<span
class="text-xs"
:class="[txGroup ? ' text-lightBlue' : 'text-footer-color']"
>
<router-link
:to="{
path: '/address',
query: {
address: from,
},
}"
>
{{ from | filterHash }}
</router-link>
</span>
</div>
<div>
<span class="text-text-color text-xs">
{{ $t('lang.trade.receiver') }} :
</span>
<span
class="text-xs"
:class="[txGroup ? ' text-lightBlue' : 'text-footer-color']"
>
<router-link
:to="{
path: '/address',
query: {
address: to,
},
}"
>
{{ to | filterHash }}
</router-link>
</span>
</div>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
import TxStatus from '../pc/txStatus.vue'
import txGroupIcon from '@/assets/images/blockChainBrowser/tradeDetail/txGroupIcon.png'
export default Vue.extend({
components: {
TxStatus,
},
props: {
blockTime: Number,
tradeG: Number,
amount: Number,
txHash: String,
from: String,
to: String,
status: Boolean,
row: Object,
hideStatus: {
type: Boolean,
default: false,
},
},
data() {
return {
txGroupIcon,
}
},
computed: {
txGroup() {
if (this.tradeG === 1 || this.tradeG === 2) {
return 'isGroupItem'
} else if (this.tradeG === 3) {
return 'isGroupItemEnd'
} else {
return ''
}
},
},
})
</script>
<style lang="scss" scoped>
.txItem {
border-bottom: 1px solid #f5f5ff;
height: 90px;
.leftLine {
position: absolute;
top: 0;
bottom: 0;
left: 0;
width: 2px;
background: rgba(79, 221, 252, 1);
z-index: 1;
}
.txGroupIcon {
position: absolute;
left: -10px;
bottom: -10px;
z-index: 2;
}
}
.txItem:last-of-type {
border-bottom: none;
}
</style>
<template>
<div class="c-vote-pack flex items-center px-3.5">
<div
class="box text-center flex flex-col justify-center"
:class="[
type !== 'vote' ? 'text-orange' : ' text-footer-color',
type !== 'vote' ? ' bg-lightOrange' : ' bg-lightBlue4',
]"
>
<div>
<span class="text-base font-bold">
{{ rewardAmount | filterAmount }}
</span>
<span class="text-xs">
YCC
</span>
</div>
<div>
{{ $t('lang.block.blockReward') }}
</div>
</div>
<div class="flex-grow" style="margin-left: 10px;">
<div
class="flex justify-between items-center"
style="margin-bottom: 2px;"
>
<div class="text-darkBlue text-sm font-bold">
<router-link
:to="{
path: '/blockDetail',
query: {
height: height,
},
}"
>
{{ height }}
</router-link>
</div>
<div class="text-text-color text-xs">
{{ timeBlock | formatTime }}
</div>
</div>
<div style="margin-bottom: 2px;">
<span class="text-text-color text-xs">
{{ $t('lang.txDetail.txHash') }}:
</span>
<span class="text-footer-color text-xs font-bold">
<router-link
:to="{
path: '/tradeHash',
query: {
hash: txHash,
},
}"
>
{{ txHash | filterHash(9) }}
</router-link>
</span>
</div>
<div>
<span class="text-text-color text-xs">
{{ $t('lang.trade.sender') }}:
</span>
<span class="text-footer-color text-xs font-bold">
<router-link
:to="{
path: '/address',
query: {
address: sender,
},
}"
>
{{ sender | filterHash(9) }}
</router-link>
</span>
</div>
</div>
</div>
</template>
<script lang="ts">
import Vue, { PropType } from 'vue'
export default Vue.extend({
props: {
type: String as PropType<'vote' | 'pack'>,
rewardAmount: Number,
height: Number,
txHash: String,
sender: String,
timeBlock: Number,
},
})
</script>
<style lang="scss" scoped>
.c-vote-pack {
height: 90px;
background: #ffffff;
border-radius: 2px;
border-bottom: 1px solid #f5f5ff;
.box {
width: 100px;
height: 66px;
border-radius: 2px;
}
}
</style>
<template>
<div class="num flow-root">
<div class="mt-2.5 flex items-center justify-between">
<div class="text-darkBlue font-bold">
{{ $t('lang.chainPerf.txNumberOnTheChain') }}
</div>
<div>
<span
v-for="(filter, i) in filters"
:key="i"
@click="currentFilter = filter"
:style="{
'margin-left': i !== 0 && '15px',
}"
class="text-text-color"
:class="{
'text-darkBlue': currentFilter === filter,
'font-bold': currentFilter === filter,
}"
>
{{ filter }}
</span>
</div>
</div>
<charts
:scale="currentFilter"
style="height: 100px;"
:grid="{
top: '12px',
bottom: '25px',
left: '50px',
right: '20px',
}"
></charts>
</div>
</template>
<script lang="ts">
import charts from '@/components/charts.vue'
import Vue from 'vue'
export default Vue.extend({
components: { charts },
data() {
return {
filters: ['D1', 'W1', 'M1', 'Y1'],
currentFilter: 'D1',
}
},
})
</script>
<style lang="scss" scoped>
.num {
padding: 0 15px;
height: 140px;
background: #ffffff;
box-shadow: 0px 1px 8px 0px rgba(31, 52, 112, 0.06);
border-radius: 2px;
}
</style>
...@@ -2,23 +2,59 @@ ...@@ -2,23 +2,59 @@
<div class="menu"> <div class="menu">
<Drawer <Drawer
width="270" width="270"
class="my-drawer"
@close="onClose" @close="onClose"
:closable="true" :closable="true"
:visible="isShow" :visible="isShow"
> >
<div class="logo mb-3.5 px-6"> <div class="logo mb-3.5 px-6">
<img src="@/assets/images/header/logo.png" width="164" alt="yuanlian"> <img src="@/assets/images/ycclogo.png" width="140" alt="yuanlian" />
</div> </div>
<ul class="menulist"> <ul class="menulist">
<li class="px-6 text-base text-title-color" :class="{'menu-active': $route.path === '/home'}" @click="goPage('/')">{{ $t('lang.home') }}</li> <li
class="px-6 text-base text-title-color"
:class="{ 'menu-active': $route.path === '/home' }"
@click="goPage('/')"
>
{{ $t('lang.home') }}
</li>
<li class="px-6 text-base text-title-color"> <li class="px-6 text-base text-title-color">
<a <a
:href="iconType === 'zh-CN' ? :href="
'https://yuanorg.oss-ap-southeast-1.aliyuncs.com/ycc/white-paper/zh.pdf' : iconType === 'zh-CN'
'https://yuanorg.oss-ap-southeast-1.aliyuncs.com/ycc/white-paper/en.pdf'" ? 'https://yuanorg.oss-ap-southeast-1.aliyuncs.com/ycc/white-paper/zh.pdf'
target="_blank">{{ $t('lang.book') }}</a> : 'https://yuanorg.oss-ap-southeast-1.aliyuncs.com/ycc/white-paper/en.pdf'
"
target="_blank"
>
{{ $t('lang.book') }}
</a>
</li>
<li
class="px-6 text-base text-title-color"
:class="{
'menu-active':
$route.path === '/newsList' || $route.path === '/newsDetails',
}"
@click="goPage('/newsList')"
>
{{ $t('lang.news') }}
</li>
<li
class="px-6 text-base text-title-color"
:class="{
'menu-active':
$route.path === '/blockChainBrowser' ||
$route.path === '/block' ||
$route.path === '/blockDetail' ||
$route.path === '/tradeHash' ||
$route.path === '/tradeList' ||
$route.path === '/address',
}"
@click="goPage('/blockChainBrowser')"
>
{{ $t('lang.blockChainBrowser') }}
</li> </li>
<li class="px-6 text-base text-title-color" :class="{'menu-active': $route.path === '/newsList' || $route.path === '/newsDetails'}" @click="goPage('/newsList')">{{ $t('lang.news') }}</li>
</ul> </ul>
</Drawer> </Drawer>
</div> </div>
...@@ -29,43 +65,47 @@ import Vue from 'vue' ...@@ -29,43 +65,47 @@ import Vue from 'vue'
import { Drawer } from 'ant-design-vue' import { Drawer } from 'ant-design-vue'
export default Vue.extend({ export default Vue.extend({
components: { components: {
Drawer Drawer,
}, },
props: { props: {
isShow: Boolean, isShow: Boolean,
iconType: { iconType: {
type: String, type: String,
default: 'zh-CN' default: 'zh-CN',
} },
}, },
methods: { methods: {
onClose() { onClose() {
this.$emit('close', true) this.$emit('close', true)
}, },
goPage(p: string) { goPage(p: string) {
this.$router.push({path: p, query: { lang: this.$route.query.lang }}) this.$router.push({ path: p, query: { lang: this.$route.query.lang } })
this.onClose() this.onClose()
} },
} },
}) })
</script> </script>
<style> <style>
.ant-drawer-close { .ant-drawer-close {
top: 9px; top: 9px;
} }
.ant-drawer-body { .ant-drawer-body {
padding-left: 0; padding-left: 0;
padding-right: 0; padding-right: 0;
} }
.my-drawer {
z-index: 3001;
}
</style> </style>
<style scoped> <style scoped>
.menulist li { .menulist li {
line-height: 48px; line-height: 48px;
} }
.menu-active { .menu-active {
background: #EFF5FF; background: #eff5ff;
} color: #2545cb;
</style> }
\ No newline at end of file </style>
<template>
<div class="b-container">
<img
src="@/assets/images/blockChainBrowser/address/yccIcon.png"
class="yccIcon"
alt=""
/>
<div class="balance-label">
{{ $t('lang.address.balance') }}
</div>
<div class="balance-value">{{ filterNum(balance / 1e8) }} YCC</div>
<div class="text-sm text-white" style="margin-top: 10px;">
{{ $t('lang.address.freeze') }}
<span class="ml-2">
{{ filterNum(frozen / 1e8) }}
YCC
</span>
</div>
<Select
style="margin-top: 73px;"
:selectedValue="selectedValue"
:optionsList="optionsList"
:searchPlaceholder="$t('lang.searchCurrency')"
@change="handleSelectChange"
></Select>
</div>
</template>
<script lang="ts">
import { filterNum } from '@/utils/utils'
import VueTypedMixins from 'vue-typed-mixins'
import Select from '../../CurrencySelect.vue'
export default VueTypedMixins().extend({
components: { Select },
props: {
balance: [Number, Object],
selectedValue: String,
frozen: [Number, Object],
optionsList: Array,
handleSelectChange: Function,
},
methods: {
filterNum,
},
})
</script>
<style scoped lang="scss">
.b-container {
width: 380px;
height: 360px;
background-color: #2545cb;
border-radius: 20px;
background-image: url('../../../../assets/images/blockChainBrowser/address/balanceBg.png');
background-position: right bottom;
background-size: 281px 302px;
background-repeat: no-repeat;
padding-top: 60px;
padding-left: 28px;
.yccIcon {
width: 30px;
height: 30px;
}
.balance-label {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ffffff;
margin-top: 20px;
}
.balance-value {
font-size: 32px;
font-family: DINAlternate-Bold, DINAlternate;
font-weight: bold;
color: #ffffff;
line-height: normal;
margin-top: 10px;
}
}
</style>
<template>
<div class="card bg-white flex text-center w-full overflow-hidden">
<div class="w-1/4 mt-10" v-for="(item, index) in list" :key="index">
<div class="text-text-color">{{ item.name }}</div>
<div
ref="father"
class="mt-4 text-title-color text-xl font-bold overflow-hidden overflow-ellipsis whitespace-nowrap"
>
<span v-if="index < 2" ref="a">
{{ filterNum(item.value / 1e8) }} YCC
</span>
<span v-else-if="index == 2" ref="b">
{{ filterNum(Number(item.value / 1e8).toFixed(2)) }}
{{ $t('lang.price.dollar') }}
</span>
<span v-else ref="c">
{{ item.value | filterNum }}
</span>
</div>
</div>
</div>
</template>
<script lang="ts">
import { filterNum } from '@/utils/utils'
import Vue, { PropType } from 'vue'
export default Vue.extend({
props: {
list: Array as PropType<{ name: string; value: string | number }[]>,
},
mounted() {
this.setFontSize()
},
methods: {
filterNum,
setFontSize() {
const father = this.$refs.father as HTMLElement[]
const a = this.$refs.a as HTMLElement[]
const b = this.$refs.b as HTMLElement[]
const c = this.$refs.c as HTMLElement[]
let beSmall = false
;[...a, ...b, ...c].some((el: HTMLElement) => {
if (el.offsetWidth >= father[0].offsetWidth) {
beSmall = true
}
})
beSmall &&
[...a, ...b, ...c].forEach((el: HTMLElement) => {
el.style.fontSize = '14px'
})
},
},
watch: {
list(newV) {
this.setFontSize()
},
},
})
</script>
<style scoped>
.card {
height: 140px;
border-radius: 4px;
}
</style>
<template>
<div class="_container">
<div class="top flex items-center">
<div class="address_label mr-2.5 my-title">
{{ $t('lang.address.address') }}
</div>
<div class="address_value mr-2.5">
{{ $route.query.address }}
</div>
<copy-btn :copyTxt="$route.query.address" class="mr-2.5">
{{ $t('lang.components.copy') }}
</copy-btn>
<div class="little-qrcode flex items-center justify-center">
<Popover placement="right" trigger="hover">
<canvas id="qrcode" style="margin: 13px;"></canvas>
<img
slot="reference"
src="@/assets/images/blockChainBrowser/address/qrcodeIcon.png"
alt=""
class="w-5 h-5 cursor-pointer"
/>
</Popover>
</div>
</div>
<div class="flex">
<Balance
class="flex-shrink-0"
:balance="balance"
:frozen="frozen"
:selectedValue="selectedValue"
:optionsList="optionsList"
:handleSelectChange="handleSelectChange"
></Balance>
<div class="w-full flex flex-col overflow-hidden">
<div class="flex-grow relative">
<div class="text-right" style="padding-right: 30px;">
<span
class="text-text-color ml-7 cursor-pointer"
v-for="(s, i) in scaleList"
:key="i"
:class="{
' text-footer-color': s === selectedScale,
}"
@click="selectedScale = s"
>
{{ s }}
</span>
</div>
<div
style="padding-left: 30px; padding-right: 30px; margin-top: 10px;"
>
<charts-in-addr
style="height: 190px;"
:scale="selectedScale"
:grid="{
top: '10px',
bottom: '25px',
left: '50px',
right: '20px',
}"
></charts-in-addr>
</div>
<!-- <img :src="chartNoDataImg" alt="" />
<div class="absolute text-text-color text-sm text-center w-full">
暂无数据
</div> -->
</div>
<card-show-trade-in-total
class="flex-shrink-0"
:list="tradeInTotalList"
></card-show-trade-in-total>
</div>
</div>
</div>
</template>
<script lang="ts">
import VueTypedMixins from 'vue-typed-mixins'
import CopyBtn from '../../CopyBtn.vue'
import { Popover } from 'element-ui'
import AddressOverview from '@/mixin/componentsMixin/AddressOverview'
import chartNoDataImg from '@/assets/images/blockChainBrowser/address/chart-no-data.png'
import Balance from './Balance.vue'
import CardShowTradeInTotal from './CardShowTradeInTotal.vue'
import ChartsInAddr from '@/components/chartsInAddr.vue'
export default VueTypedMixins(AddressOverview).extend({
components: { CopyBtn, Popover, Balance, CardShowTradeInTotal, ChartsInAddr },
props: {
balance: [Number, Object],
selectedValue: String,
frozen: [Number, Object],
optionsList: Array,
handleSelectChange: Function,
},
data() {
return {
chartNoDataImg,
scaleList: ['W1', 'M1', 'M6', 'Y1'],
selectedScale: 'W1',
}
},
})
</script>
<style lang="scss" scoped>
._container {
width: 1200px;
height: 440px;
background: #ffffff;
box-shadow: 0px 2px 15px 0px rgba(31, 52, 112, 0.06);
border-radius: 4px;
.top {
height: 80px;
padding-left: 30px;
}
.address_value {
font-size: 18px;
font-family: PingFang-SC-Bold, PingFang-SC;
font-weight: bold;
color: #2545cb;
}
.little-qrcode {
width: 30px;
height: 30px;
background-color: rgba(37, 69, 203, 0.1);
border-radius: 4px;
}
}
</style>
<style>
.el-popover,
.el-popper {
z-index: 3001 !important;
}
</style>
<template>
<div
class="left-box"
:style="{ backgroundImage: `url(${leftBoxbgPng})` }"
v-loading="loading"
element-loading-text="Loading..."
element-loading-spinner="el-icon-loading"
>
<div class="flex">
<div class="flex _left overflow-hidden flex-shrink-0">
<img
src="@/assets/images/blockChainBrowser/blockDetail/block.png"
class="blockIcon"
alt=""
/>
<div class="overflow-hidden">
<div class="my-title">
{{ $t('lang.txDetail.height') }}
</div>
<div class="my-block-height overflow-hidden overflow-ellipsis">
{{ $route.query.height }}
</div>
</div>
</div>
<div class="_middle flex-shrink-0">
<div class="my-title">
{{ $t('lang.block.blockRevenue') }}
</div>
<div class="my-benifit">
{{ $route.query.height | filterBlockReward }}
</div>
</div>
<div class="_right flex-shrink-0">
<div class="my-title">
{{ $t('lang.block.txCount') }}
</div>
<div class="my-benifit">
{{ data.txCount }}
</div>
</div>
</div>
<div class="flex items-center" style="margin-top: 35px;">
<div class="my-title theTitle">{{ $t('lang.block.timestamp') }}</div>
<div class="my-content1">{{ data.blockTime | formatTime }}</div>
</div>
<div class="flex items-center">
<div class="my-title theTitle">{{ $t('lang.block.hash') }}</div>
<div class="my-content1">
{{ data.hash }}
</div>
<copy-btn :copyTxt="data.hash" class="ml-4"></copy-btn>
</div>
<div class="flex items-center">
<div class="my-title theTitle">
{{ $t('lang.block.merkelgen') }}
</div>
<div class="my-content1">
{{ data.txHash }}
</div>
<copy-btn :copyTxt="data.txHash" class="ml-4"></copy-btn>
</div>
<div class="flex items-center">
<div class="my-title theTitle">
{{ $t('lang.block.stateHash') }}
</div>
<div class="my-content1">
{{ data.stateHash }}
</div>
<copy-btn :copyTxt="data.stateHash" class="ml-4"></copy-btn>
</div>
</div>
</template>
<script lang="ts">
// eslint-disable-next-line @typescript-eslint/no-var-requires
const leftBoxbgPng = require('@/assets/images/blockChainBrowser/blockDetail/leftBoxbg.png')
import Vue from 'vue'
import CopyBtn from '../../CopyBtn.vue'
export default Vue.extend({
components: { CopyBtn },
props: {
data: Object,
loading: Boolean,
},
data() {
return {
leftBoxbgPng,
}
},
})
</script>
<style>
.left-box {
width: 870px;
height: 330px;
background: #ffffff;
box-shadow: 0px 2px 15px 0px rgba(31, 52, 112, 0.06);
border-radius: 4px;
background-position: center;
background-size: cover;
padding-top: 42px;
padding-left: 30px;
}
.blockIcon {
width: 52px;
height: 52px;
margin-right: 20px;
}
._left {
width: 360px;
}
._middle {
width: 260px;
}
._right {
width: 220px;
}
.theTitle {
width: 100px;
margin-bottom: 10px;
margin-top: 10px;
}
</style>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment