Browse Source

page commit

master
fave3722 3 years ago
parent
commit
66a44546cd
  1. 5
      .eslintrc.js
  2. 24
      .gitignore
  3. 3
      .vscode/extensions.json
  4. 16
      README.md
  5. 5
      auto-imports.d.ts
  6. 41
      components.d.ts
  7. 13
      index.html
  8. 5
      mixin.scss
  9. 5177
      package-lock.json
  10. 32
      package.json
  11. 6
      postcss.config.cjs
  12. 1
      public/vite.svg
  13. 10
      src/App.vue
  14. BIN
      src/assets/Icons/cancel.png
  15. BIN
      src/assets/Icons/check-circle.png
  16. BIN
      src/assets/Icons/filter_none.png
  17. BIN
      src/assets/Icons/footer_logo.png
  18. 8
      src/assets/Icons/index.ts
  19. BIN
      src/assets/Icons/info.png
  20. BIN
      src/assets/Icons/label.png
  21. BIN
      src/assets/bg/homepage-topbg.png
  22. 1
      src/assets/vue.svg
  23. 34
      src/components/base/UpperLowerSwitch.vue
  24. 7
      src/components/base/baseType.ts
  25. 60
      src/components/base/hp_card.vue
  26. 48
      src/components/footer.vue
  27. 10
      src/components/icons/iconType.ts
  28. 39
      src/components/icons/index.vue
  29. 164
      src/components/table/constant.ts
  30. 75
      src/components/table/dBase/bkRow.vue
  31. 35
      src/components/table/dBase/detailsRow.vue
  32. 46
      src/components/table/dBase/hpRow.vue
  33. 42
      src/components/table/dBase/tHeader.vue
  34. 110
      src/components/table/dBase/transactDetailsRow.vue
  35. 69
      src/components/table/desktop/bkTable.vue
  36. 50
      src/components/table/desktop/bkTableDetails.vue
  37. 35
      src/components/table/desktop/hpTable.vue
  38. 69
      src/components/table/desktop/transactDetails.vue
  39. 69
      src/components/table/desktop/transactTable.vue
  40. 41
      src/components/table/desktop/zExtraStyle.scss
  41. 27
      src/components/table/mBase/detailsRow.vue
  42. 35
      src/components/table/mBase/mobileCard.vue
  43. 43
      src/components/table/mBase/nowrapRow.vue
  44. 37
      src/components/table/mBase/transactCard.vue
  45. 79
      src/components/table/mBase/transactDetailsRow.vue
  46. 90
      src/components/table/mobile/bkTable.vue
  47. 59
      src/components/table/mobile/bkTableDetails.vue
  48. 70
      src/components/table/mobile/transactDetails.vue
  49. 90
      src/components/table/mobile/transactTable.vue
  50. 23
      src/components/table/table.ts
  51. 5
      src/components/table/tool.ts
  52. 3
      src/index.scss
  53. 9
      src/main.ts
  54. 66
      src/pages/HomePage/index.scss
  55. 172
      src/pages/HomePage/index.vue
  56. 66
      src/pages/TableBlock/Block/details.vue
  57. 103
      src/pages/TableBlock/Block/index.vue
  58. 31
      src/pages/TableBlock/Tabs.vue
  59. 66
      src/pages/TableBlock/Tokens/details.vue
  60. 15
      src/pages/TableBlock/Tokens/index.vue
  61. 118
      src/pages/TableBlock/Transactions/details.vue
  62. 139
      src/pages/TableBlock/Transactions/index.vue
  63. 90
      src/pages/TableBlock/index.scss
  64. 93
      src/pages/TableBlock/index.vue
  65. 39
      src/routes.ts
  66. 80
      src/style.scss
  67. 7
      src/vite-env.d.ts
  68. 41
      tailwind.config.cjs
  69. 22
      tsconfig.json
  70. 9
      tsconfig.node.json
  71. 31
      vite.config.ts
  72. 12
      vue.config.js
  73. 1719
      yarn.lock

5
.eslintrc.js

@ -0,0 +1,5 @@
module.exports = {
env: {
'vue/setup-compiler-macros': true
}
}

24
.gitignore

@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

3
.vscode/extensions.json

@ -0,0 +1,3 @@
{
"recommendations": ["Vue.volar"]
}

16
README.md

@ -0,0 +1,16 @@
# Vue 3 + TypeScript + Vite
This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
## Recommended IDE Setup
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar)
## Type Support For `.vue` Imports in TS
Since TypeScript cannot handle type information for `.vue` imports, they are shimmed to be a generic Vue component type by default. In most cases this is fine if you don't really care about component prop types outside of templates. However, if you wish to get actual prop types in `.vue` imports (for example to get props validation when using manual `h(...)` calls), you can enable Volar's Take Over mode by following these steps:
1. Run `Extensions: Show Built-in Extensions` from VS Code's command palette, look for `TypeScript and JavaScript Language Features`, then right click and select `Disable (Workspace)`. By default, Take Over mode will enable itself if the default TypeScript extension is disabled.
2. Reload the VS Code window by running `Developer: Reload Window` from the command palette.
You can learn more about Take Over mode [here](https://github.com/johnsoncodehk/volar/discussions/471).

5
auto-imports.d.ts

@ -0,0 +1,5 @@
// Generated by 'unplugin-auto-import'
export {}
declare global {
}

41
components.d.ts

@ -0,0 +1,41 @@
// generated by unplugin-vue-components
// We suggest you to commit this file into source control
// Read more: https://github.com/vuejs/core/pull/3399
import '@vue/runtime-core'
export {}
declare module '@vue/runtime-core' {
export interface GlobalComponents {
BkRow: typeof import('./src/components/table/dBase/bkRow.vue')['default']
BkTable: typeof import('./src/components/table/desktop/bkTable.vue')['default']
BkTableDetails: typeof import('./src/components/table/desktop/bkTableDetails.vue')['default']
Card: typeof import('./src/components/table/base/card.vue')['default']
ColRow: typeof import('./src/components/table/mBase/colRow.vue')['default']
DetailsRow: typeof import('./src/components/table/dBase/detailsRow.vue')['default']
ElIcon: typeof import('element-plus/es')['ElIcon']
ElInput: typeof import('element-plus/es')['ElInput']
ElPagination: typeof import('element-plus/es')['ElPagination']
ElTable: typeof import('element-plus/es')['ElTable']
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
ElTabPane: typeof import('element-plus/es')['ElTabPane']
ElTabs: typeof import('element-plus/es')['ElTabs']
Footer: typeof import('./src/components/footer.vue')['default']
Hp_card: typeof import('./src/components/base/hp_card.vue')['default']
HpRow: typeof import('./src/components/table/dBase/hpRow.vue')['default']
HpTable: typeof import('./src/components/table/desktop/hpTable.vue')['default']
Icons: typeof import('./src/components/icons/index.vue')['default']
MobileCard: typeof import('./src/components/table/mBase/mobileCard.vue')['default']
NowrapRow: typeof import('./src/components/table/mBase/nowrapRow.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
Row: typeof import('./src/components/table/row.vue')['default']
THeader: typeof import('./src/components/table/dBase/tHeader.vue')['default']
TransactCard: typeof import('./src/components/table/mBase/transactCard.vue')['default']
TransactDetails: typeof import('./src/components/table/desktop/transactDetails.vue')['default']
TransactDetailsRow: typeof import('./src/components/table/dBase/transactDetailsRow.vue')['default']
TransactTable: typeof import('./src/components/table/desktop/transactTable.vue')['default']
TRow: typeof import('./src/components/table/base/tRow.vue')['default']
UpperLowerSwitch: typeof import('./src/components/base/UpperLowerSwitch.vue')['default']
}
}

13
index.html

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue + TS</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

5
mixin.scss

@ -0,0 +1,5 @@
@mixin mobile {
@media screen and (max-width: 1439px) {
@content
}
}

5177
package-lock.json

File diff suppressed because it is too large

32
package.json

@ -0,0 +1,32 @@
{
"name": "metaforce-scan",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview"
},
"dependencies": {
"element-plus": "^2.2.14",
"vue": "^3.2.37",
"vue-router": "4"
},
"devDependencies": {
"@types/node": "^18.7.13",
"@vitejs/plugin-vue": "^3.0.3",
"autoprefixer": "^10.4.8",
"postcss": "^8.4.16",
"sass": "^1.54.5",
"sass-loader": "^10.3.1",
"style-resources-loader": "^1.5.0",
"tailwindcss": "^3.1.8",
"typescript": "^4.6.4",
"unplugin-auto-import": "^0.11.2",
"unplugin-vue-components": "^0.22.4",
"vite": "^3.0.7",
"vue-cli-plugin-style-resources-loader": "^0.1.5",
"vue-tsc": "^0.39.5"
}
}

6
postcss.config.cjs

@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

1
public/vite.svg

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

10
src/App.vue

@ -0,0 +1,10 @@
<template>
<div>
<!-- <router-link to="/">首页</router-link>&nbsp;
<router-link to="/TableBlock">block</router-link>&nbsp;
<hr /> -->
<router-view></router-view>
</div>
</template>
<script setup lang="ts"></script>
<style scoped></style>

BIN
src/assets/Icons/cancel.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 691 B

BIN
src/assets/Icons/check-circle.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 641 B

BIN
src/assets/Icons/filter_none.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 511 B

BIN
src/assets/Icons/footer_logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

8
src/assets/Icons/index.ts

@ -0,0 +1,8 @@
import label from './label.png'
import footer_logo from './footer_logo.png'
import filter_none from './filter_none.png'
import info from './info.png'
import check_circle from './check-circle.png'
import cancel from './cancel.png'
export { label, footer_logo, filter_none, info, check_circle, cancel }

BIN
src/assets/Icons/info.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 851 B

BIN
src/assets/Icons/label.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/assets/bg/homepage-topbg.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

1
src/assets/vue.svg

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>

After

Width:  |  Height:  |  Size: 496 B

34
src/components/base/UpperLowerSwitch.vue

@ -0,0 +1,34 @@
<template>
<div
class="flex flex-1 flex-row mt-[28px] justify-end mobile:justify-center items-center"
:class="className"
>
<div
class="h-[24px] w-[24px] desktop:mr-[6px] mobile:mr-[38px] base-structure"
>
<el-icon :color="'#FFFFFF'" :size="10"><ArrowLeftBold /></el-icon>
</div>
<div class="h-[24px] px-[8px] base-structure">
<span class="text-[12px] font-medium text-white">{{ current }}</span>
</div>
<div
class="h-[24px] w-[24px] desktop:ml-[6px] mobile:ml-[38px] base-structure"
>
<el-icon :color="'#FFFFFF'" :size="10"><ArrowRightBold /></el-icon>
</div>
</div>
</template>
<script setup lang="ts">
import { ArrowLeftBold, ArrowRightBold } from '@element-plus/icons-vue'
defineProps({
current: String,
className: String,
})
</script>
<style scoped>
.base-structure {
@apply flex justify-center items-center bg-black-3B3B3C rounded-[4px];
}
</style>

7
src/components/base/baseType.ts

@ -0,0 +1,7 @@
export interface HpCard {
txnHash: string
from: string
to: string
time: string
fee: string
}

60
src/components/base/hp_card.vue

@ -0,0 +1,60 @@
<template>
<div class="px-[20px] pb-[24px] hp-card">
<div
class="flex flex-row justify-between pt-[24px]"
v-for="(item, index) in lists"
:key="index"
>
<p class="text-blue-65B5FF text-[14px] font-medium">{{ item.lable }}</p>
<p class="text-white text-[14px] font-medium">{{ item.value }}</p>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import type { PropType } from 'vue'
import { HpCard } from './baseType'
export default defineComponent({
props: {
option: Object as PropType<HpCard>,
},
setup(props) {
const { option } = props
return {
lists: [
{
lable: 'Txn Hash',
value: option?.txnHash,
},
{
lable: 'From',
value: option?.from,
},
{
lable: 'To',
value: option?.to,
},
{
lable: 'Date / Time',
value: option?.time,
},
{
lable: 'Fee(MBC)',
value: option?.fee,
},
],
}
},
})
</script>
<style lang="scss" scoped>
.hp-card {
border-bottom: 1px solid #3b3b3c;
}
.hp-card:last-child {
border-bottom: none;
}
</style>

48
src/components/footer.vue

@ -0,0 +1,48 @@
<template>
<div
class="bg-black-19191A desktop:mt-[108px] desktop:pt-[42px] desktop:px-[120px] mobile:mt-[48px] mobile:px-[20px] mobile:pt-[28px] pb-[26px]"
>
<div class="flex flex-1 desktop:flex-row mobile:flex-col justify-between">
<!-- 左侧 -->
<div class="flex flex-row">
<div class="w-[134px]">
<p class="pb-[22px] text-[15px] text-white">Tokens</p>
<p class="pb-[22px] text-[15px] text-gray-BBB">NFT</p>
<p class="pb-[22px] text-[15px] text-gray-BBB">VNFT</p>
<p class="pb-[22px] text-[15px] text-gray-BBB">KNFT</p>
<p class="pb-[22px] text-[15px] text-green-1DE9B6">More</p>
</div>
<div class="w-[134px]">
<p class="pb-[22px] text-[15px] text-white">Blockchain</p>
<p class="pb-[22px] text-[15px] text-gray-BBB">View Blocks</p>
<p class="pb-[22px] text-[15px] text-gray-BBB">View Txs</p>
</div>
</div>
<!-- 右侧 -->
<div class="mobile:mt-[18px]">
<img :src="iconList.footer_logo" class="w-[172px] h-[33px]" />
<p
class="desktop:w-[369px] desktop:text-[15px] mobile:text-[14px] mt-[28px] text-white"
>
MetaForce is a tool for inspecting and analyzing EVM based
blockchains. Blockchain explorer for MetaForce Networks.
</p>
</div>
</div>
<div
class="mt-[24px] mobile:hidden"
style="border-bottom: 1px solid #3b3b3c"
/>
<div
class="flex justify-center items-center desktop:mt-[20px] mobile:mt-[42px]"
>
<p class="text-[12px] text-gray-7D7D7E">Copyright© 2022 MetaForce</p>
</div>
</div>
</template>
<script setup lang="ts">
import * as iconList from '@src/assets/Icons/index'
</script>
<style lang="scss" scoped></style>

10
src/components/icons/iconType.ts

@ -0,0 +1,10 @@
import * as iconList from '@src/assets/Icons/index'
namespace Icons {
export interface Props {
size?: number | { w: number; h: number }
url: keyof typeof iconList
}
}
export default Icons

39
src/components/icons/index.vue

@ -0,0 +1,39 @@
<template>
<img
class="align-middle"
:src="url && iconList[url]"
:class="`w-${size}-icon h-${size}-icon`"
/>
</template>
<script setup lang="ts">
import { defineProps } from 'vue'
import type { PropType } from 'vue'
import * as iconList from '../../assets/Icons/index'
import Icons from './iconType'
defineProps({
url: String as PropType<Icons.Props['url']>,
size: [Number, Object],
})
</script>
<style lang="scss" scoped>
.w-12-icon {
width: 12px;
}
.w-14-icon {
width: 14px;
}
.w-24-icon {
width: 24px;
}
.h-12-icon {
height: 12px;
}
.h-14-icon {
height: 14px;
}
.h-24-icon {
width: 24px;
}
</style>

164
src/components/table/constant.ts

@ -0,0 +1,164 @@
// bkTable表配置
export const bkTableCollocate = {
labels: ['Block', 'date', 'Miner', 'Gas Limit', 'Gas Used'], // 表头
sequence: ['block', 'date', 'miner', 'gasLimit', 'gasUsed'], // 对应数据的变量名称
// 数据颜色
colorSequence: [
'text-blue-65B5FF',
'text-gray-7D7D7E',
'text-blue-65B5FF',
'',
'',
],
}
// detailsbkTable表配置
export const detailsCollocate = {
labels: [
'Block Height',
'Timestamp',
'Transactions',
'Miner',
'Size',
'Hash',
'Parent Hash',
'Difficulty',
'Total Difficulty',
'Gas Used',
'Gas Limit',
'Nonce',
], // 表头
sequence: [
'blockHeight',
'timestamp',
'transactions',
'miner',
'size',
'hash',
'parentHash',
'difficulty',
'totalDifficulty',
'gasUsed',
'gasLimit',
'nonce',
], // 对应数据的变量名称
colorSequence: [
'',
'',
'',
'text-blue-65B5FF',
'',
'',
'text-blue-65B5FF',
'',
'',
'',
'',
'',
], // 数据颜色
isCopys: [
false,
false,
false,
true,
false,
false,
true,
false,
false,
false,
false,
false,
], // 是否可复制
}
// transactTable表配置
export const transactTableCollocate = {
labels: [
'Hash',
'Block',
'Smart contract',
'Age',
'From',
'To',
'Result',
'TX Fee',
], // 表头
sequence: [
'hash',
'block',
'smartContract',
'age',
'from',
'to',
'result',
'tXFee',
], // 对应数据的变量名称
// 数据颜色
colorSequence: [
'text-blue-65B5FF',
'text-blue-65B5FF',
'',
'text-gray-7D7D7E',
'text-blue-65B5FF',
'text-blue-65B5FF',
'',
'',
'',
],
}
// transactDetails表配置
export const transactDetailsCollocate = {
labels: [
'Transaction Hash',
'Result',
'Time',
'From',
'Interacted With (To)',
'Tokens Transferred',
'Value',
'Transaction Fee',
'Gas Price',
'Transaction Type',
'Gas Limit',
], // 表头
sequence: [
'transactionHash',
'result',
'time',
'from',
'interactedWithTo',
'tokensTransferred',
'value',
'transactionFee',
'gasPrice',
'transactionType',
'gasLimit',
], // 对应数据的变量名称
colorSequence: [
'',
'',
'text-blue-65B5FF',
'',
'text-blue-65B5FF',
'text-blue-65B5FF',
'',
'',
'',
'',
'',
'',
], // 数据颜色
isCopys: [
true,
false,
false,
false,
true,
true,
false,
false,
false,
false,
false,
false,
], // 是否可复制
}

75
src/components/table/dBase/bkRow.vue

@ -0,0 +1,75 @@
<template>
<div
:class="last ? 'rounded-b-[10px]' : ''"
class="flex flex-1 flex-row bg-black-19191A hover:bg-black-272728 items-center py-[24px] px-[34px]"
>
<div
class="flex flex-1 justify-start"
v-for="(item, index) in sequence"
:key="index"
>
<div
:class="
item === 'smartContract'
? 'bg-gray-303031 px-[12px] py-[4px] rounded-[4px]'
: ''
"
>
<span
v-if="item !== 'result'"
:class="colorSequence[index] || 'text-white'"
class="text-[14px] font-medium"
>{{ values[item] }}
</span>
<div
v-else
class="px-[12px] py-[4px] rounded-[4px] w-[87px] flex flex-row items-center"
:class="
values.result === 'Success' ? 'bg-green-2EAA7D' : 'bg-red-C4403E'
"
>
<Icons
:url="values.result === 'Success' ? 'check_circle' : 'cancel'"
:size="12"
/>
<span
:class="colorSequence[index] || 'text-white'"
class="text-[12px] font-medium ml-[2px]"
>{{ values[item] }}
</span>
</div>
</div>
</div>
</div>
<div
v-if="!last"
class="mx-[34px]"
style="border-bottom: 1px solid #3b3b3c"
/>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import type { PropType } from 'vue'
import TableTypes from '../table'
import Icons from '@src/components/icons/index.vue'
export default defineComponent({
props: {
sequence: Array as PropType<TableTypes.tRow['sequence']>,
values: Object as PropType<TableTypes.tRow['values']>,
colorSequence: Array as PropType<TableTypes.tRow['colorSequence']>,
last: Boolean,
},
setup(props) {
return {
sequence: props.sequence,
colorSequence: props.colorSequence || [],
values: props.values || {},
last: props.last,
}
},
components: { Icons },
})
</script>
<style lang="scss" scoped></style>

35
src/components/table/dBase/detailsRow.vue

@ -0,0 +1,35 @@
<template>
<div
class="flex desktop:flex-row desktop:items-center desktop:py-[16px] mobile:flex-col mobile:items-start mobile:py-[18px]"
>
<div class="flex flex-1 flex-row max-w-[255px] items-center">
<Icons url="info" :size="14" />
<p class="ml-[7px] text-gray-BBB text-[14px] font-normal">{{ title }}</p>
</div>
<div
class="flex flex-1 flex-row justify-start items-center mobile:mt-[15px]"
>
<p :class="valueColor || 'text-white'" class="text-[15px] font-normal">
{{ value }}
</p>
<Icons v-if="isCopy" url="filter_none" :size="24" class="ml-[10px]" />
</div>
</div>
<div
:class="isLast ? 'mobile:hidden' : ''"
style="border-bottom: 1px solid #3b3b3c"
/>
</template>
<script setup lang="ts">
import Icons from '@src/components/icons/index.vue'
const props = defineProps({
title: String,
value: String as any,
valueColor: String,
isCopy: Boolean,
isLast: Boolean,
})
</script>
<style scoped></style>

46
src/components/table/dBase/hpRow.vue

@ -0,0 +1,46 @@
<template>
<div
:class="last ? 'rounded-b-[10px]' : ''"
class="flex flex-1 flex-row bg-black-19191A hover:bg-black-272728 items-center py-[24px] px-[34px]"
>
<div
class="flex flex-1 justify-start"
v-for="(item, index) in sequence"
:key="index"
>
<span
:class="[item === 'time' ? 'text-gray-7D7D7E' : 'text-white']"
class="text-white text-[14px] font-medium"
>{{ values[item] }}
</span>
</div>
</div>
<div
v-show="!last"
class="mx-[34px]"
style="border-bottom: 1px solid #3b3b3c"
/>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import type { PropType } from 'vue'
import TableTypes from '../table'
export default defineComponent({
props: {
sequence: Array as PropType<TableTypes.tRow['sequence']>,
values: Object as PropType<TableTypes.tRow['values']>,
last: Boolean,
},
setup(props) {
console.log(props)
return {
sequence: props.sequence,
values: props.values || {},
last: props.last,
}
},
})
</script>
<style lang="scss" scoped></style>

42
src/components/table/dBase/tHeader.vue

@ -0,0 +1,42 @@
<template>
<div
:class="bgColor || ''"
class="flex flex-1 flex-col rounded-t-[10px] px-[34px]"
>
<div class="flex flex-1 flex-row items-center py-[24px]">
<div
class="flex flex-1 justify-start"
v-for="(item, index) in list"
:key="index"
>
<span
:class="textColor || 'text-blue-65B5FF'"
class="text-[16px] font-bold"
>{{ item }}</span
>
</div>
</div>
<div style="border-bottom: 1px solid #3b3b3c" />
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import type { PropType } from 'vue'
import TableTypes from '../table'
export default defineComponent({
props: {
list: Array as PropType<TableTypes.tHeader['list']>,
bgColor: String as PropType<TableTypes.tHeader['bgColor']>,
textColor: String as PropType<TableTypes.tHeader['textColor']>,
},
setup(props) {
return {
list: props.list,
bgColor: props.bgColor,
}
},
})
</script>
<style scoped></style>

110
src/components/table/dBase/transactDetailsRow.vue

@ -0,0 +1,110 @@
<template>
<div
class="flex desktop:flex-row desktop:py-[16px] mobile:flex-col mobile:items-start mobile:py-[18px]"
:class="title === 'Tokens Transferred' ? 'desktop:py-[0px]' : ''"
>
<div
class="flex flex-1 flex-row max-w-[255px]"
:class="
title === 'Tokens Transferred'
? 'items-start pt-[16px]'
: 'items-center'
"
>
<Icons url="info" :size="14" />
<p class="ml-[7px] text-gray-BBB text-[14px] font-normal">
{{ title }}
</p>
</div>
<div
class="flex flex-1 flex-row justify-start items-center mobile:mt-[15px]"
v-if="title === 'Result'"
>
<div
class="flex flex-row items-center rounded-[4px] px-[12px] py-[4px] bg-green-2EAA7D"
>
<Icons
:url="value === 'Success' ? 'check_circle' : 'cancel'"
:size="12"
/>
<p
:class="valueColor || 'text-white'"
class="text-[12px] font-normal align-middle"
>
{{ value }}
</p>
</div>
</div>
<div
class="flex flex-1 flex-col justify-start mobile:mt-[15px]"
v-if="title === 'Tokens Transferred'"
>
<div
class="flex flex-row items-center py-[16px] mobile:flex-col mobile:items-start mobile:py-[18px]"
:class="
index === list.length - 1
? 'border-b-0'
: 'border-b-[1px] border-b-black-3B3B3C'
"
v-for="(item, index) in list"
:key="index + item"
>
<div class="flex flex-1 flex-row max-w-[71px] items-center">
<p class="text-gray-BBB text-[14px] font-normal">
{{ item }}
</p>
</div>
<div
class="flex flex-1 flex-row justify-start items-center mobile:mt-[15px]"
>
<p class="text-[15px] font-normal text-blue-65B5FF">
{{ value[item] }}
</p>
<Icons v-if="isCopy" url="filter_none" :size="24" class="ml-[10px]" />
</div>
</div>
</div>
<div
class="flex flex-1 flex-row justify-start items-center mobile:mt-[15px]"
v-if="title !== 'Tokens Transferred' && title !== 'Result'"
>
<p
:class="valueColor || 'text-white'"
class="text-[15px] font-normal leading-[24px]"
>
{{ value }}
</p>
<Icons v-if="isCopy" url="filter_none" :size="24" class="ml-[10px]" />
</div>
</div>
<div
:class="isLast ? 'mobile:hidden' : ''"
style="border-bottom: 1px solid #3b3b3c"
/>
</template>
<script setup lang="ts">
import Icons from '@src/components/icons/index.vue'
import { onMounted, ref } from 'vue'
const props = defineProps({
title: String,
value: [String, Object] as any,
valueColor: String,
isCopy: Boolean,
isLast: Boolean,
})
onMounted(() => {
console.log(props.title)
if (props.title === 'Tokens Transferred') {
console.log(1)
}
if (typeof props.value === 'object') {
list.value = Object.keys(props.value)
}
})
const list = ref<string[]>([])
</script>
<style scoped></style>

69
src/components/table/desktop/bkTable.vue

@ -0,0 +1,69 @@
<template>
<div class="rounded-[10px] bg-black-19191A pb-[47px] rounded-b-[10px]">
<t-header
:list="invariable.labels"
bg-color="bg-black-006"
textColor="text-white"
/>
<div
v-for="(item, index) in currentData"
:key="item?.date + index"
@click="routerLink(item.block)"
>
<bk-row
:sequence="invariable.sequence"
:values="item"
:colorSequence="invariable.colorSequence"
/>
</div>
<div
class="bk-pagination flex flex-row items-center justify-end pt-[32px] pr-[34px]"
>
<el-pagination
:page-size="invariable.pageSize"
layout="prev, pager, next, jumper"
v-model:current-page="currentPage"
:total="paginationState.totalPage"
@current-change="handleCurrentChange"
/>
<span class="text-white text-[14px] font-normal">Page</span>
</div>
</div>
</template>
<script setup lang="ts">
import { defineProps, reactive, ref } from 'vue'
import THeader from '../dBase/tHeader.vue'
import BkRow from '../dBase/bkRow.vue'
import { dimensionalUpgrade } from '../tool'
import { bkTableCollocate } from '../constant'
import router from '@src/routes'
const props = defineProps({
data: Array as any,
})
const invariable = {
...bkTableCollocate,
pageSize: 10, //
}
const paginationState = reactive({
totalPage:
Math.floor(props?.data.length / invariable.pageSize + 1) *
invariable.pageSize, //
totalData: dimensionalUpgrade(props?.data, invariable.pageSize), //
})
let currentPage = ref(1) //
let currentData = ref(paginationState.totalData[currentPage.value - 1]) //
const handleCurrentChange = (page: number) => {
currentData.value = paginationState.totalData[page - 1]
}
//
const routerLink = (id: string | number) => router.push(`/TableBlock/${id}`)
</script>
<style lang="scss">
@import './zExtraStyle.scss';
</style>

50
src/components/table/desktop/bkTableDetails.vue

@ -0,0 +1,50 @@
<template>
<div
class="rounded-[10px] bg-black-19191A rounded-b-[10px] px-[34px] pt-[12px] pb-[28px]"
>
<details-row
v-for="(item, index) in invariable.labels"
:key="index + item"
:title="item"
:value="data[invariable.sequence[index]]"
:value-color="invariable.colorSequence[index]"
:is-copy="invariable.isCopys[index]"
/>
<upper-lower-switch :current="'Block'" />
</div>
</template>
<script setup lang="ts">
import { defineProps, onMounted, ref } from 'vue'
import DetailsRow from '../dBase/detailsRow.vue'
import UpperLowerSwitch from '@src/components/base/UpperLowerSwitch.vue'
import { detailsCollocate } from '../constant'
const props = defineProps({
id: Array as any,
})
onMounted(() => {
setTimeout(() => {
data.value = {
blockHeight: '12333',
timestamp: '12333',
transactions: '12333',
miner: '12333',
size: '12333',
hash: '12333',
parentHash: '12333',
difficulty: '12333',
totalDifficulty: '12333',
gasUsed: '12333',
gasLimit: '12333',
nonce: '12333',
}
}, 1000)
})
const data = ref<any>({})
const invariable = {
...detailsCollocate,
}
</script>
<style lang="scss"></style>

35
src/components/table/desktop/hpTable.vue

@ -0,0 +1,35 @@
<template>
<div class="rounded-[10px]">
<t-header :list="thList" />
<hp-row
v-for="(item, index) in data"
:key="index"
:sequence="sequence"
:values="item"
:last="index === data.length - 1"
/>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import THeader from '../dBase/tHeader.vue'
import HpRow from '../dBase/hpRow.vue'
export default defineComponent({
components: { THeader, HpRow },
props: {
data: Array as any,
},
setup(props) {
const { data } = props
return {
thList: ['Txn Hash', 'From', 'To', 'Date / Time', 'Fee(MBC)'],
sequence: ['txnHash', 'from', 'to', 'time', 'fee'],
data: data,
}
},
})
</script>
<style scoped></style>

69
src/components/table/desktop/transactDetails.vue

@ -0,0 +1,69 @@
<template>
<div
class="rounded-[10px] bg-black-19191A rounded-b-[10px] px-[34px] pt-[12px] pb-[28px]"
>
<transact-details-row
v-for="(item, index) in invariable.labels"
:key="index + item"
:title="item"
:value="data[invariable.sequence[index]]"
:value-color="invariable.colorSequence[index]"
:is-copy="invariable.isCopys[index]"
/>
<upper-lower-switch :current="'Transaction Details'" />
</div>
</template>
<script setup lang="ts">
import { defineProps, onMounted, ref } from 'vue'
import transactDetailsRow from '../dBase/transactDetailsRow.vue'
import UpperLowerSwitch from '@src/components/base/UpperLowerSwitch.vue'
import { transactDetailsCollocate } from '../constant'
const props = defineProps({
id: Array as any,
})
onMounted(() => {
setTimeout(() => {
data.value = {
transactionHash: '1323',
result: '1323',
time: '1323',
from: '1323',
interactedWithTo: '1323',
tokensTransferred: {
from: '123',
to: '234',
for: '345',
},
value: '1323',
transactionFee: '1323',
gasPrice: '1323',
transactionType: '1323',
gasLimit: '1323',
}
}, 0)
})
const data = ref<any>({
transactionHash: '1323',
result: '1323',
time: '1323',
from: '1323',
interactedWithTo: '1323',
tokensTransferred: {
from: '123',
to: '234',
for: '345',
},
value: '1323',
transactionFee: '1323',
gasPrice: '1323',
transactionType: '1323',
gasLimit: '1323',
})
const invariable = {
...transactDetailsCollocate,
}
</script>
<style lang="scss"></style>

69
src/components/table/desktop/transactTable.vue

@ -0,0 +1,69 @@
<template>
<div class="rounded-[10px] bg-black-19191A pb-[47px] rounded-b-[10px]">
<t-header
:list="invariable.labels"
bg-color="bg-black-006"
textColor="text-white"
/>
<div
v-for="(item, index) in currentData"
:key="item?.hash + index"
@click="routerLink(item.block)"
>
<bk-row
:sequence="invariable.sequence"
:values="item"
:colorSequence="invariable.colorSequence"
/>
</div>
<div
class="bk-pagination flex flex-row items-center justify-end pt-[32px] pr-[34px]"
>
<el-pagination
:page-size="invariable.pageSize"
layout="prev, pager, next, jumper"
v-model:current-page="currentPage"
:total="paginationState.totalPage"
@current-change="handleCurrentChange"
/>
<span class="text-white text-[14px] font-normal">Page</span>
</div>
</div>
</template>
<script setup lang="ts">
import { defineProps, reactive, ref } from 'vue'
import THeader from '../dBase/tHeader.vue'
import BkRow from '../dBase/bkRow.vue'
import { dimensionalUpgrade } from '../tool'
import { transactTableCollocate } from '../constant'
import router from '@src/routes'
const props = defineProps({
data: Array as any,
})
const invariable = {
...transactTableCollocate,
pageSize: 10, //
}
const paginationState = reactive({
totalPage:
Math.floor(props?.data.length / invariable.pageSize + 1) *
invariable.pageSize, //
totalData: dimensionalUpgrade(props?.data, invariable.pageSize), //
})
let currentPage = ref(1) //
let currentData = ref(paginationState.totalData[currentPage.value - 1]) //
const handleCurrentChange = (page: number) => {
currentData.value = paginationState.totalData[page - 1]
}
//
const routerLink = (id: string | number) => router.push(`/TableBlock/tx/${id}`)
</script>
<style lang="scss">
@import './zExtraStyle.scss';
</style>

41
src/components/table/desktop/zExtraStyle.scss

@ -0,0 +1,41 @@
.bk-pagination {
.el-pagination {
.btn-prev,
.btn-next {
background: #19191a;
}
.el-pager {
.number,
.btn-quicknext {
display: flex;
justify-content: center;
align-items: center;
height: 30px;
width: 30px;
margin: 0px 8px;
box-sizing: border-box;
background: #19191a;
border: 1px solid #ffffff;
border-radius: 5px;
color: #ffffff;
}
.is-active {
background: #8659ff;
border: 1px solid #8659ff;
}
}
.el-pagination__jump {
color: #ffffff;
}
.el-input__wrapper {
background: #19191a;
.el-input__inner {
color: #ffffff;
}
}
.el-input__wrapper.is-focus {
box-shadow: 0 0 0 1px var(--el-input-border-color, var(--el-border-color))
inset;
}
}
}

27
src/components/table/mBase/detailsRow.vue

@ -0,0 +1,27 @@
<template>
<div class="flex flex-row items-center py-[16px]">
<div class="flex flex-1 flex-row max-w-[255px] items-center">
<Icons url="info" :size="14" />
<p class="ml-[7px] text-gray-BBB text-[14px] font-normal">{{ title }}</p>
</div>
<div class="flex flex-1 flex-row justify-start items-center">
<p :class="valueColor || 'text-white'" class="text-[15px] font-normal">
<span>{{ value }}</span
><Icons v-if="isCopy" url="filter_none" :size="24" class="ml-[10px]" />
</p>
</div>
</div>
<div style="border-bottom: 1px solid #3b3b3c" />
</template>
<script setup lang="ts">
import Icons from '@src/components/icons/index.vue'
const props = defineProps({
title: String,
value: String,
valueColor: String,
isCopy: Boolean,
})
</script>
<style scoped></style>

35
src/components/table/mBase/mobileCard.vue

@ -0,0 +1,35 @@
<template>
<div>
<div
class="flex flex-1 flex-wrap mobile-card pt-[14px] border-b-[1px] border-b-black-3B3B3C"
>
<div
class="flex flex-half min-w-6/12"
v-for="(item, index) in invariable.labels"
:key="index"
@click="routerLink(cardData.block)"
>
<nowrap-row
:title="item"
:value="cardData[invariable.sequence[index]]"
:value-color="invariable.colorSequence[index]"
/>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import router from '@src/routes'
import { defineProps } from 'vue'
import { bkTableCollocate } from '../constant'
import nowrapRow from './nowrapRow.vue'
const props = defineProps({
cardData: Object as any,
})
const invariable = { ...bkTableCollocate }
//
const routerLink = (id: string | number) => router.push(`/TableBlock/${id}`)
</script>
<style lang="scss" scoped></style>

43
src/components/table/mBase/nowrapRow.vue

@ -0,0 +1,43 @@
<template>
<div
class="flex flex-half flex-col min-w-6/12 px-[20px] py-[10px]"
:class="valueColor || 'text-white'"
>
<p class="text-[14px] font-medium text-gray-C1C0C0">{{ title }}</p>
<p class="flex flex-auto text-[13px] font-normal">
<div v-if="isSuccess" class="flex flex-row items-center rounded-[4px] px-[12px] py-[4px] min-w-[87px]" :class="value === 'Success' ? 'bg-green-2EAA7D' : 'bg-red-C4403E'">
<Icons
:url="value === 'Success' ? 'check_circle' : 'cancel'"
:size="12"
/>
<span
class="ml-[2px] text-[12px]"
>
{{ value }}
</span>
</div>
<span
:class="isWrap ? 'px-[12px] py-[4px] bg-gray-303031 rounded-[4px]' : ''"
v-else
>
{{ value }}
</span>
</p>
</div>
</template>
<script setup lang="ts">
import { defineProps } from 'vue'
import Icons from '@src/components/icons/index.vue'
const props = defineProps({
title: String,
value: String,
valueColor: String,
isWrap: Boolean,
isSuccess: Boolean,
})
</script>
<style scoped></style>

37
src/components/table/mBase/transactCard.vue

@ -0,0 +1,37 @@
<template>
<div>
<div
class="flex flex-1 flex-wrap mobile-card pt-[14px] border-b-[1px] border-b-black-3B3B3C"
>
<div
class="flex flex-half min-w-6/12"
v-for="(item, index) in invariable.labels"
:key="index"
@click="routerLink(cardData.block)"
>
<nowrap-row
:title="item"
:value="cardData[invariable.sequence[index]]"
:value-color="invariable.colorSequence[index]"
:is-wrap="item === 'Smart contract'"
:is-success="item === 'Result'"
/>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import router from '@src/routes'
import { defineProps } from 'vue'
import { transactTableCollocate } from '../constant'
import nowrapRow from './nowrapRow.vue'
const props = defineProps({
cardData: Object as any,
})
const invariable = { ...transactTableCollocate }
//
const routerLink = (id: string | number) => router.push(`/TableBlock/tx/${id}`)
</script>
<style lang="scss" scoped></style>

79
src/components/table/mBase/transactDetailsRow.vue

@ -0,0 +1,79 @@
<template>
<div class="flex flex-col py-[16px]">
<div class="flex flex-1 flex-row max-w-[255px] items-center">
<Icons url="info" :size="14" />
<p class="ml-[7px] text-gray-BBB text-[14px] font-normal">{{ title }}</p>
</div>
<div class="flex flex-1 flex-row justify-start items-center mt-[15px]">
<div
:class="valueColor || 'text-white'"
class="text-[15px] font-normal break-all"
>
<div v-if="title === 'Tokens Transferred'">
<div
class="flex flex-col pl-[20px]"
v-for="(item, index) in list"
:key="index + item"
>
<div class="flex flex-1 flex-row items-center mt-[15px]">
<p class="text-gray-BBB text-[14px] font-normal">
{{ item }}
</p>
</div>
<p class="text-[15px] font-normal text-blue-65B5FF break-all">
<span>
{{ value[item] }}
<Icons
v-if="isCopy"
url="filter_none"
:size="24"
class="ml-[10px] inline"
/>
</span>
</p>
</div>
</div>
<div
v-if="title === 'Result'"
class="flex flex-row items-center rounded-[4px] px-[12px] py-[4px] min-w-[87px]"
:class="value === 'Success' ? 'bg-green-2EAA7D' : 'bg-red-C4403E'"
>
<Icons
:url="value === 'Success' ? 'check_circle' : 'cancel'"
:size="12"
/>
<span class="ml-[2px] text-[12px]">
{{ value }}
</span>
</div>
<span v-if="title !== 'Result' && title !== 'Tokens Transferred'">
{{ value }}
<Icons
v-if="isCopy"
url="filter_none"
:size="24"
class="ml-[10px] inline"
/>
</span>
</div>
</div>
</div>
<div style="border-bottom: 1px solid #3b3b3c" />
</template>
<script setup lang="ts">
import Icons from '@src/components/icons/index.vue'
import { onMounted, ref } from 'vue'
const props = defineProps({
title: String,
value: [String, Object] as any,
valueColor: String,
isCopy: Boolean,
})
onMounted(() => {
list.value = typeof props.value === 'object' ? Object.keys(props.value) : []
})
const list = ref<string[]>([])
</script>
<style scoped></style>

90
src/components/table/mobile/bkTable.vue

@ -0,0 +1,90 @@
<template>
<div class="rounded-[10px] bg-black-19191A pb-[20px] rounded-b-[10px]">
<mobile-card
v-for="(item, index) in currentData"
:key="index"
:card-data="item"
/>
<div
class="bk-pagination flex flex-row items-center justify-center pt-[32px]"
>
<el-pagination
:page-size="invariable.pageSize"
layout="prev, pager, next"
v-model:current-page="currentPage"
:total="paginationState.totalPage"
@current-change="handleCurrentChange"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { defineProps, reactive, ref } from 'vue'
import MobileCard from '@src/components/table/mBase/mobileCard.vue'
import { dimensionalUpgrade } from '../tool'
const props = defineProps({
data: Array as any,
})
const invariable = {
pageSize: 5, //
}
const paginationState = reactive({
totalPage:
Math.floor(props?.data.length / invariable.pageSize + 1) *
invariable.pageSize, //
totalData: dimensionalUpgrade(props?.data, invariable.pageSize), //
})
let currentPage = ref(1) //
let currentData = ref(paginationState.totalData[currentPage.value - 1]) //
const handleCurrentChange = (page: number) => {
currentData.value = paginationState.totalData[page - 1]
}
</script>
<style lang="scss">
.bk-pagination {
.el-pagination {
.btn-prev,
.btn-next {
background: #19191a;
}
.el-pager {
.number,
.btn-quicknext {
display: flex;
justify-content: center;
align-items: center;
height: 30px;
width: 30px;
margin: 0px 8px;
box-sizing: border-box;
background: #19191a;
border: 1px solid #ffffff;
border-radius: 5px;
color: #ffffff;
}
.is-active {
background: #8659ff;
border: 1px solid #8659ff;
}
}
.el-pagination__jump {
color: #ffffff;
}
.el-input__wrapper {
background: #19191a;
.el-input__inner {
color: #ffffff;
}
}
.el-input__wrapper.is-focus {
box-shadow: 0 0 0 1px var(--el-input-border-color, var(--el-border-color))
inset;
}
}
}
</style>

59
src/components/table/mobile/bkTableDetails.vue

@ -0,0 +1,59 @@
<template>
<div
class="rounded-[10px] bg-black-19191A rounded-b-[10px] desktop:px-[34px] mobile:px-[20px] pt-[12px] desktop:pb-[28px]"
>
<upper-lower-switch
:current="'Block'"
:class="'mt-[0px] justify-center'"
:space-class="''"
/>
<div
v-for="(item, index) in invariable.labels"
:key="index + item"
class="mt-[20px]"
>
<details-row
:title="item"
:value="data[invariable.sequence[index]]"
:value-color="invariable.colorSequence[index]"
:is-copy="invariable.isCopys[index]"
:is-last="index === invariable.labels.length - 1 ? true : false"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { defineProps, onMounted, ref } from 'vue'
import DetailsRow from '../dBase/detailsRow.vue'
import UpperLowerSwitch from '@src/components/base/UpperLowerSwitch.vue'
import { detailsCollocate } from '../constant'
const props = defineProps({
id: Array as any,
})
onMounted(() => {
setTimeout(() => {
data.value = {
blockHeight: '12333',
timestamp: '12333',
transactions: '12333',
miner: '12333',
size: '12333',
hash: '12333',
parentHash: '12333',
difficulty: '12333',
totalDifficulty: '12333',
gasUsed: '12333',
gasLimit: '12333',
nonce: '12333',
}
}, 1000)
})
const data = ref<any>({})
const invariable = {
...detailsCollocate,
}
</script>
<style scoped></style>

70
src/components/table/mobile/transactDetails.vue

@ -0,0 +1,70 @@
<template>
<div
class="rounded-[10px] bg-black-19191A rounded-b-[10px] px-[20px] pt-[12px] pb-[28px]"
>
<upper-lower-switch :current="'Transaction Details'" />
<transact-details-row
v-for="(item, index) in invariable.labels"
:key="index + item"
:title="item"
:value="data[invariable.sequence[index]]"
:value-color="invariable.colorSequence[index]"
:is-copy="invariable.isCopys[index]"
/>
</div>
</template>
<script setup lang="ts">
import { defineProps, onMounted, ref } from 'vue'
import transactDetailsRow from '../mBase/transactDetailsRow.vue'
import UpperLowerSwitch from '@src/components/base/UpperLowerSwitch.vue'
import { transactDetailsCollocate } from '../constant'
const props = defineProps({
id: Array as any,
})
onMounted(() => {
setTimeout(() => {
data.value = {
transactionHash: '1323',
result: 'Success',
time: '1323',
from: '1323',
interactedWithTo: '1323',
tokensTransferred: {
from: '123',
to: '234',
for: '345',
},
value: '1323',
transactionFee: '1323',
gasPrice: '1323',
transactionType: '1323',
gasLimit: '1323',
}
}, 0)
})
const data = ref<any>({
transactionHash: '1323',
result: '1323',
time: '1323',
from: '1323',
interactedWithTo: '1323',
tokensTransferred: {
from: '123',
to: '234',
for: '345',
},
value: '1323',
transactionFee: '1323',
gasPrice: '1323',
transactionType: '1323',
gasLimit: '1323',
})
const invariable = {
...transactDetailsCollocate,
}
</script>
<style lang="scss"></style>

90
src/components/table/mobile/transactTable.vue

@ -0,0 +1,90 @@
<template>
<div class="rounded-[10px] bg-black-19191A pb-[20px] rounded-b-[10px]">
<transact-card
v-for="(item, index) in currentData"
:key="index"
:card-data="item"
/>
<div
class="bk-pagination flex flex-row items-center justify-center pt-[32px]"
>
<el-pagination
:page-size="invariable.pageSize"
layout="prev, pager, next"
v-model:current-page="currentPage"
:total="paginationState.totalPage"
@current-change="handleCurrentChange"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { defineProps, reactive, ref } from 'vue'
import TransactCard from '../mBase/transactCard.vue'
import { dimensionalUpgrade } from '../tool'
const props = defineProps({
data: Array as any,
})
const invariable = {
pageSize: 5, //
}
const paginationState = reactive({
totalPage:
Math.floor(props?.data.length / invariable.pageSize + 1) *
invariable.pageSize, //
totalData: dimensionalUpgrade(props?.data, invariable.pageSize), //
})
let currentPage = ref(1) //
let currentData = ref(paginationState.totalData[currentPage.value - 1]) //
const handleCurrentChange = (page: number) => {
currentData.value = paginationState.totalData[page - 1]
}
</script>
<style lang="scss">
.bk-pagination {
.el-pagination {
.btn-prev,
.btn-next {
background: #19191a;
}
.el-pager {
.number,
.btn-quicknext {
display: flex;
justify-content: center;
align-items: center;
height: 30px;
width: 30px;
margin: 0px 8px;
box-sizing: border-box;
background: #19191a;
border: 1px solid #ffffff;
border-radius: 5px;
color: #ffffff;
}
.is-active {
background: #8659ff;
border: 1px solid #8659ff;
}
}
.el-pagination__jump {
color: #ffffff;
}
.el-input__wrapper {
background: #19191a;
.el-input__inner {
color: #ffffff;
}
}
.el-input__wrapper.is-focus {
box-shadow: 0 0 0 1px var(--el-input-border-color, var(--el-border-color))
inset;
}
}
}
</style>

23
src/components/table/table.ts

@ -0,0 +1,23 @@
namespace TableTypes {
export interface tHeader {
list: any[]
bgColor?: string
textColor?: string
}
export interface tRow {
sequence: string[]
colorSequence: string[]
values: Record<any, any>
}
export interface mobileCard {
cardData: {
block: string
date: string
miner: string
gasLimit: string
gasUsed: string
}
}
}
export default TableTypes

5
src/components/table/tool.ts

@ -0,0 +1,5 @@
export const dimensionalUpgrade = (arr: any[], includeIndex: number) => {
return arr.reduce((p, c, i) => {
return i % includeIndex === 0 ? [...p, [c]] : (p[p.length - 1].push(c), p)
}, [])
}

3
src/index.scss

@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

9
src/main.ts

@ -0,0 +1,9 @@
import { createApp } from 'vue'
import router from './routes'
import ElementPlus from 'element-plus'
import './style.scss'
import './index.scss'
import 'element-plus/dist/index.css'
import App from './App.vue'
createApp(App).use(router).use(ElementPlus).mount('#app')

66
src/pages/HomePage/index.scss

@ -0,0 +1,66 @@
@import '/mixin.scss';
.hp-input-wrapper {
&:hover {
box-shadow: rgba(0,0,0,0);
}
.el-input__wrapper{
padding: 0 0;
background: #262626;
border: none;
outline: none;
box-shadow: none !important;
box-sizing: border-box;
.el-input__prefix {
.el-input__icon{
width: 20px;
height: 20px;
@include mobile{
width: 18px;
height: 18px;
}
}
}
.el-input__inner {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
font-size: 15px;
@include mobile{
font-size: 12px;
}
}
}
}
.latest-transactions{
.el-icon {
@include mobile{
display: none;
}
}
}
.hp-table {
--el-table-border-color: none !important;
.el-table__body{
table-layout: inherit !important;
// width: 1100px !important;
}
.el-table__cell{
background: #19191A !important;
border-bottom: 1px solid #3B3B3C !important;
padding: 24px 0px !important;
box-sizing: border-box;
width: 1100px!important;
}
.el-table__row:last-child {
.el-table__cell{
border-bottom: none !important;
}
}
.el-table__row{
width: 1200px !important;
// border-bottom: 1px solid #3B3B3C !important;
&:hover .el-table__cell{
background: #272728 !important;
}
}
}

172
src/pages/HomePage/index.vue

@ -0,0 +1,172 @@
<template>
<div class="bg-black desktop:pt-[122px] mobile:pt-[39px]">
<div
class="bg-home-page bg-cover bg-center bg-no-repeat desktop:w-[1440px] desktop:h-[535.5px] desktop:pt-[70px] mobile:w-full mobile:h-[219px] mobile:pt-[25px]"
>
<div class="flex flex-1 justify-center items-center">
<img
:src="url"
class="desktop:w-[70px] desktop:h-[40px] mobile:w-[40px] mobile:h-[24px]"
/>
<span
class="desktop:text-[50px] mobile:text-[24px] font-semibold text-white ml-[16px]"
>MetaForce Scan</span
>
</div>
<div
class="flex flex-1 desktop:h-[65px] mobile:h-[40px] justify-center items-center desktop:mt-[68px] mobile:mt-[32px]"
>
<div class="flex flex-1 desktop:px-[282px] mobile:px-[20px]">
<el-input
v-model="input"
class="bg-black desktop:h-[65px] desktop:pl-[33px] mobile:h-[40px] mobile:pl-[15.69px] mobile:text-[12px] rounded-[100px] overflow-hidden hp-input-wrapper"
placeholder="Search by Address/Token symbol/Name/Transaction hash/Bock number"
:prefix-icon="Search"
:input-style="{ background: '#262626' }"
/>
</div>
</div>
</div>
<!-- 中间部分 -->
<div
class="desktop:px-[120px] desktop:mt-[-111.5px] mobile:px-[20px] mobile:mt-[-51px]"
>
<!-- Network Overview -->
<div
class="bg-black-19191A pt-[34px] pb-[38px] mobile:py-[28px] rounded-[10px]"
>
<p
class="text-white text-[20px] font-semibold desktop:pl-[34px] mobile:pl-[20px] mobile:text-[20px] mobile:font-semibold"
>
Network Overview
</p>
<div
class="flex flex-1 desktop:flex-row desktop:mt-[35px] mobile:flex-col"
>
<div
v-for="(item, index) in overview"
:key="index"
class="flex flex-1 flex-col desktop:pl-[34px] mobile:pl-[20px] mobile:mt-[28px]"
>
<p class="text-gray-969697 text-[15px]">{{ item.label }}</p>
<p class="text-[36px] text-white font-semibold mt-[12px]">
{{ item.value }}
</p>
</div>
</div>
</div>
<!-- Latest Transactions -->
<div
class="flex flex-1 flex-row justify-between items-center desktop:pt-[56px] desktop:pb-[27px] mobile:pt-[37px] mobile:pb-[17px] latest-transactions"
>
<p
class="text-white font-semibold desktop:text-[20px] mobile:text-[18px] desktop:pl-[34px]"
>
Latest Transactions
</p>
<div
class="flex flex-row justify-center items-center bg-black-19191A rounded-full desktop:py-[8px] desktop:px-[14px] mobile:py-[6px] mobile:px-[15px] cursor-pointer"
@click="jumpRoute"
>
<p
class="text-white font-medium desktop:text-[14px] mobile:text-[12px]"
>
View All Txs
</p>
<el-icon color="#FFFFFF" class="ml-[8px] mobile:hidden">
<Right />
</el-icon>
</div>
</div>
<!-- table -->
<div class="bg-black-19191A rounded-[10px]">
<div class="mobile:hidden rounded-[10px]">
<hp-table :data="tableData" />
</div>
<div class="desktop:hidden">
<hp-card
v-for="(item, index) in tableData"
:key="index"
:option="item"
/>
</div>
</div>
</div>
<!-- footer -->
<Footer />
</div>
</template>
<script lang="ts">
import { defineComponent } from '@vue/runtime-core'
import { Search, Right } from '@element-plus/icons-vue'
import hpCard from '@src/components/base/hp_card.vue'
import * as iconList from '../../assets/Icons/index'
import router from '@src/routes'
import HpTable from '@src/components/table/desktop/hpTable.vue'
import Footer from '../../components/footer.vue'
export default defineComponent({
components: {
Search,
Right,
hpCard,
HpTable,
Footer,
},
setup() {
return {
Search: Search,
url: iconList.label,
footer_logo: iconList.footer_logo,
input: '',
//
overview: [
{
label: 'Block',
value: '5880',
},
{
label: 'Transaction',
value: '5880',
},
{
label: 'Block Time',
value: '5880',
},
{
label: 'Tokens',
value: '5880',
},
],
//
tableData: [
{
txnHash: '0123123',
from: '0xshd......hhhh6',
to: '0xhhh.....77hhhh',
time: '2022-08-10 09:50:17',
fee: '0.0000021',
},
{
txnHash: '0xdhdqwsh1',
from: '0xshdhhhh6',
to: '0xhhh77hhhh',
time: '2022-08-10 09:50:17',
fee: '0.0000021',
},
],
}
},
methods: {
jumpRoute() {
// router.push({ name: 'TableBlock', params: {} })
router.push('TableBlock')
},
},
})
</script>
<style lang="sass">
@import './index.scss'
</style>

66
src/pages/TableBlock/Block/details.vue

@ -0,0 +1,66 @@
<template>
<div
class="tableBlock-tabs desktop:mt-[-435.5px] mobile:mt-[-51px] desktop:px-[120px] mobile:px-[20px]"
>
<div class="flex items-center">
<el-icon
:color="'#FFFFFF'"
class="cursor-pointer icon-size"
@click="goBack"
><ArrowLeftBold
/></el-icon>
<span
class="desktop:text-[26px] mobile:text-[18px] text-white font-medium desktop:ml-[12px] mobile:ml-[8px] cursor-pointer"
@click="goBack"
>Block Details</span
>
</div>
<div class="mobile:hidden mt-[38px]">
<bk-desktop-details />
</div>
<div class="desktop:hidden mt-[38px]">
<bk-mobile-details />
</div>
<!-- 下面的选项 -->
<div
class="flex flex-1 w-full bg-black-19191A mt-[56px] rounded-[10px] overflow-hidden"
>
<div class="details-tabs w-full">
<el-tabs v-model="active" class="w-full">
<el-tab-pane label="Transactions" name="Block">
<div class="flex flex-1 justify-center items-center h-[210px]">
<p class="text-white text-[14px] font-normal opacity-80">
There are no transactions for this block.
</p>
</div>
</el-tab-pane>
<!-- 待扩展 -->
<!-- <el-tab-pane label="Transactions" name="Transactions">
<Transactions />
</el-tab-pane>
<el-tab-pane label="Tokens" name="Tokens">
<Tokens />
</el-tab-pane> -->
</el-tabs>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ArrowLeftBold } from '@element-plus/icons-vue'
import BkDesktopDetails from '@src/components/table/desktop/bkTableDetails.vue'
import BkMobileDetails from '@src/components/table/mobile/bkTableDetails.vue'
import router from '@src/routes'
import { ref } from 'vue'
const active = ref('Block')
// 退
const goBack = () => router.back()
</script>
<style lang="scss">
@import '../index.scss';
</style>

103
src/pages/TableBlock/Block/index.vue

@ -0,0 +1,103 @@
<template>
<div class="w-full desktop:pt-[23px] mobile:pt-[13px]">
<div class="mobile:hidden">
<desktop-bk-table :data="tableData" />
</div>
<div class="desktop:hidden">
<mobile-bk-table :data="tableData" />
</div>
</div>
</template>
<script setup lang="ts">
import DesktopBkTable from '@src/components/table/desktop/bkTable.vue'
import MobileBkTable from '@src/components/table/mobile/bkTable.vue'
const tableData = [
{
block: '0xdhd.....qwsh1',
date: '0xshd......hhhh623',
miner: '0xhhh.....77hhhh',
gasLimit: '2022-08-10 09:50:17',
gasUsed: '0.0000021',
},
{
block: '0xdhd.....qwsh1',
date: '0xshd......hhhh612312',
miner: '0xhhh.....77hhhh',
gasLimit: '2022-08-10 09:50:17',
gasUsed: '0.0000021',
},
{
block: '0xdhd.....qwsh1',
date: '0xshd......hhhh63222',
miner: '0xhhh.....77hhhh',
gasLimit: '2022-08-10 09:50:17',
gasUsed: '0.0000021',
},
{
block: '0xdhd.....qwsh1',
date: '0xshd......hhhh6sdc',
miner: '0xhhh.....77hhhh',
gasLimit: '2022-08-10 09:50:17',
gasUsed: '0.0000021',
},
{
block: '0xdhd.....qwsh1',
date: '0xshd......hhhh6csdc',
miner: '0xhhh.....77hhhh',
gasLimit: '2022-08-10 09:50:17',
gasUsed: '0.0000021',
},
{
block: '0xdhd.....qwsh1',
date: '0xshd......hhhh6csd',
miner: '0xhhh.....77hhhh',
gasLimit: '2022-08-10 09:50:17',
gasUsed: '0.0000021',
},
{
block: '0xdhd.....qwsh1',
date: '0xshd......hhhh6cs',
miner: '0xhhh.....77hhhh',
gasLimit: '2022-08-10 09:50:17',
gasUsed: '0.0000021',
},
{
block: '0xdhd.....qwsh1',
date: '0xshd......hhhh6geergeg',
miner: '0xhhh.....77hhhh',
gasLimit: '2022-08-10 09:50:17',
gasUsed: '0.0000021',
},
{
block: '0xdhd.....qwsh1',
date: '0xshd......hhhh6SWE',
miner: '0xhhh.....77hhhh',
gasLimit: '2022-08-10 09:50:17',
gasUsed: '0.0000021',
},
{
block: '0xdhd.....qwsh1',
date: '0xshd......hhhh6FWE',
miner: '0xhhh.....77hhhh',
gasLimit: '2022-08-10 09:50:17',
gasUsed: '0.0000021',
},
{
block: '0xdhd.....qwsh1',
date: '0xshd......hhhh6VDFV21',
miner: '0xhhh.....77hhhh',
gasLimit: '2022-08-10 09:50:17',
gasUsed: '0.0000021',
},
{
block: '0xdhd.....qwsh1',
date: '0xshd......hhhh621DSC',
miner: '0xhhh.....77hhhh',
gasLimit: '2022-08-10 09:50:17',
gasUsed: '0.0000021',
},
]
</script>
<style scoped></style>

31
src/pages/TableBlock/Tabs.vue

@ -0,0 +1,31 @@
<template>
<div
class="tableBlock-tabs desktop:mt-[-435.5px] mobile:mt-[-51px] desktop:px-[120px] mobile:px-[20px]"
>
<el-tabs v-model="active" class="demo-tabs" @tab-click="handleClick">
<el-tab-pane label="Block" name="Block">
<Block />
</el-tab-pane>
<el-tab-pane label="Transactions" name="Transactions">
<Transactions />
</el-tab-pane>
<el-tab-pane label="Tokens" name="Tokens">
<Tokens />
</el-tab-pane>
</el-tabs>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import Block from './Block/index.vue'
import Transactions from './Transactions/index.vue'
import Tokens from './Tokens/index.vue'
const active = ref('Block')
const handleClick = () => {}
</script>
<style lang="scss">
@import './index.scss';
</style>

66
src/pages/TableBlock/Tokens/details.vue

@ -0,0 +1,66 @@
<template>
<div
class="tableBlock-tabs desktop:mt-[-435.5px] mobile:mt-[-51px] desktop:px-[120px] mobile:px-[20px]"
>
<div class="flex items-center">
<el-icon
:color="'#FFFFFF'"
class="cursor-pointer icon-size"
@click="goBack"
><ArrowLeftBold
/></el-icon>
<span
class="desktop:text-[26px] mobile:text-[18px] text-white font-medium desktop:ml-[12px] mobile:ml-[8px] cursor-pointer"
@click="goBack"
>Block Details</span
>
</div>
<div class="mobile:hidden mt-[38px]">
<transact-details />
</div>
<div class="desktop:hidden mt-[38px]">
<bk-mobile-details />
</div>
<!-- 下面的选项 -->
<div
class="flex flex-1 w-full bg-black-19191A mt-[56px] rounded-[10px] overflow-hidden"
>
<div class="details-tabs w-full">
<el-tabs v-model="active" class="w-full">
<el-tab-pane label="Transactions" name="Block">
<div class="flex flex-1 justify-center items-center h-[210px]">
<p class="text-white text-[14px] font-normal opacity-80">
There are no transactions for this block.
</p>
</div>
</el-tab-pane>
<!-- 待扩展 -->
<!-- <el-tab-pane label="Transactions" name="Transactions">
<Transactions />
</el-tab-pane>
<el-tab-pane label="Tokens" name="Tokens">
<Tokens />
</el-tab-pane> -->
</el-tabs>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ArrowLeftBold } from '@element-plus/icons-vue'
import transactDetails from '@src/components/table/desktop/transactDetails.vue'
import BkMobileDetails from '@src/components/table/mobile/bkTableDetails.vue'
import router from '@src/routes'
import { ref } from 'vue'
const active = ref('Block')
// 退
const goBack = () => router.back()
</script>
<style lang="scss">
@import '../index.scss';
</style>

15
src/pages/TableBlock/Tokens/index.vue

@ -0,0 +1,15 @@
<template>
<div class="h-[600px] w-full"></div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
setup() {
return {}
},
})
</script>
<style scoped></style>

118
src/pages/TableBlock/Transactions/details.vue

@ -0,0 +1,118 @@
<template>
<div
class="tableBlock-tabs desktop:mt-[-435.5px] mobile:mt-[-51px] desktop:px-[120px] mobile:px-[20px]"
>
<div class="flex items-center">
<el-icon
:color="'#FFFFFF'"
class="cursor-pointer icon-size"
@click="goBack"
><ArrowLeftBold
/></el-icon>
<span
class="desktop:text-[26px] mobile:text-[18px] text-white font-medium desktop:ml-[12px] mobile:ml-[8px] cursor-pointer"
@click="goBack"
>Transaction Details</span
>
</div>
<div class="mobile:hidden mt-[38px]">
<desktop-transact-details />
</div>
<div class="desktop:hidden mt-[38px]">
<mobile-transact-details />
</div>
<!-- 下面的选项 -->
<div
class="flex flex-1 w-full bg-black-19191A mt-[56px] rounded-[10px] overflow-hidden"
>
<div class="details-tabs w-full">
<el-tabs v-model="active" class="w-full">
<el-tab-pane label="Token Transfers" name="tokenTransfers">
<div class="flex flex-1 justify-center items-center h-[210px]">
<p class="text-white text-[14px] font-normal opacity-80">
There are no transactions for this block.
</p>
</div>
</el-tab-pane>
<!-- logs -->
<el-tab-pane label="Logs" name="logs">
<div class="flex flex-1 flex-col px-[34px] pb-[30px]">
<p
class="flex flex-1 text-[22px] font-semibold text-white py-[26px]"
>
Logs
</p>
<div
class="bg-black-2B2B2C text-white text-[15px] px-[34px] py-[16px] rounded-[10px]"
>
<div
class="flex flex-1 flex-row px-[20px] py-[16px] border-b-[1px] border-b-black-3B3B3C"
>
<p class="min-w-[185px] text-gray-BBB">Address</p>
<p class="text-blue-65B5FF">
0x6c4bb7121d1cf8d395a3d295d1d9e5fa85f3a342
</p>
</div>
<div
class="flex flex-1 flex-row px-[20px] py-[16px] border-b-[1px] border-b-black-3B3B3C"
>
<p class="min-w-[185px] text-gray-BBB">Address</p>
<div>
<p>
[1]
0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
</p>
<p class="mt-[16px]">
[1]
0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
</p>
<p class="mt-[16px]">
[1]
0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
</p>
</div>
</div>
<div
class="flex flex-1 flex-row px-[20px] py-[16px] border-b-[1px] border-b-black-3B3B3C"
>
<p class="min-w-[185px] text-gray-BBB">Address</p>
<p>0x6c4bb7121d1cf8d395a3d295d1d9e5fa85f3a342</p>
</div>
<div class="flex flex-1 flex-row px-[20px] py-[16px]">
<p class="min-w-[185px] text-gray-BBB">Address</p>
<p>0x6c4bb7121d1cf8d395a3d295d1d9e5fa85f3a342</p>
</div>
</div>
<upper-lower-switch :current="'page'" />
</div>
</el-tab-pane>
<!-- 待扩展 -->
<!-- <el-tab-pane label="Transactions" name="Transactions">
<Transactions />
</el-tab-pane>
<el-tab-pane label="Tokens" name="Tokens">
<Tokens />
</el-tab-pane> -->
</el-tabs>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ArrowLeftBold } from '@element-plus/icons-vue'
import DesktopTransactDetails from '@src/components/table/desktop/transactDetails.vue'
import MobileTransactDetails from '@src/components/table/mobile/transactDetails.vue'
import router from '@src/routes'
import { ref } from 'vue'
const active = ref('logs')
// 退
const goBack = () => router.back()
</script>
<style lang="scss">
@import '../index.scss';
</style>

139
src/pages/TableBlock/Transactions/index.vue

@ -0,0 +1,139 @@
<template>
<div class="w-full desktop:pt-[23px] mobile:pt-[13px]">
<div class="mobile:hidden">
<desktop-transact-table :data="tableData" />
</div>
<div class="desktop:hidden">
<mobile-transact-table :data="tableData" />
</div>
</div>
</template>
<script setup lang="ts">
import DesktopTransactTable from '@src/components/table/desktop/transactTable.vue'
import MobileTransactTable from '@src/components/table/mobile/transactTable.vue'
const tableData = [
{
hash: '0x1956...e1ea6',
block: '1017882',
smartContract: '0x3b9aca00',
age: '14 seconds ago',
from: '0x14f1... 4f0ba',
to: '0x14f1... 4f0ba',
result: 'Success',
tXFee: '0.000021',
},
{
hash: '0x1956...e1ea6',
block: '1017882',
smartContract: '0x3b9aca00',
age: '14 seconds ago',
from: '0x14f1... 4f0ba',
to: '0x14f1... 4f0ba',
result: 'Faild',
tXFee: '0.000021',
},
{
hash: '0x1956...e1ea6',
block: '1017882',
smartContract: '0x3b9aca00',
age: '14 seconds ago',
from: '0x14f1... 4f0ba',
to: '0x14f1... 4f0ba',
result: 'Success',
tXFee: '0.000021',
},
{
hash: '0x1956...e1ea6',
block: '1017882',
smartContract: '0x3b9aca00',
age: '14 seconds ago',
from: '0x14f1... 4f0ba',
to: '0x14f1... 4f0ba',
result: 'Success',
tXFee: '0.000021',
},
{
hash: '0x1956...e1ea6',
block: '1017882',
smartContract: '0x3b9aca00',
age: '14 seconds ago',
from: '0x14f1... 4f0ba',
to: '0x14f1... 4f0ba',
result: 'Success',
tXFee: '0.000021',
},
{
hash: '0x1956...e1ea6',
block: '1017882',
smartContract: '0x3b9aca00',
age: '14 seconds ago',
from: '0x14f1... 4f0ba',
to: '0x14f1... 4f0ba',
result: 'Success',
tXFee: '0.000021',
},
{
hash: '0x1956...e1ea6',
block: '1017882',
smartContract: '0x3b9aca00',
age: '14 seconds ago',
from: '0x14f1... 4f0ba',
to: '0x14f1... 4f0ba',
result: 'Success',
tXFee: '0.000021',
},
{
hash: '0x1956...e1ea6',
block: '1017882',
smartContract: '0x3b9aca00',
age: '14 seconds ago',
from: '0x14f1... 4f0ba',
to: '0x14f1... 4f0ba',
result: 'Success',
tXFee: '0.000021',
},
{
hash: '0x1956...e1ea6',
block: '1017882',
smartContract: '0x3b9aca00',
age: '14 seconds ago',
from: '0x14f1... 4f0ba',
to: '0x14f1... 4f0ba',
result: 'Success',
tXFee: '0.000021',
},
{
hash: '0x1956...e1ea6',
block: '1017882',
smartContract: '0x3b9aca00',
age: '14 seconds ago',
from: '0x14f1... 4f0ba',
to: '0x14f1... 4f0ba',
result: 'Success',
tXFee: '0.000021',
},
{
hash: '0x1956...e1ea6',
block: '1017882',
smartContract: '0x3b9aca00',
age: '14 seconds ago',
from: '0x14f1... 4f0ba',
to: '0x14f1... 4f0ba',
result: 'Success',
tXFee: '0.000021',
},
{
hash: '0x1956...e1ea6',
block: '1017882',
smartContract: '0x3b9aca00',
age: '14 seconds ago',
from: '0x14f1... 4f0ba',
to: '0x14f1... 4f0ba',
result: 'Success',
tXFee: '0.000021',
},
]
</script>
<style scoped></style>

90
src/pages/TableBlock/index.scss

@ -0,0 +1,90 @@
@import '/mixin.scss';
// 主页的
.tableBlock-tabs {
.icon-size{
font-size: 22px !important;
@include mobile {
font-size: 18px !important;
}
}
.el-tabs__active-bar {
height: 4px;
// width: 32px !important;
// transform: translateX(calc(calc(getWidth() / 3 - 32px) / 2)) !important;
// height: $w !important;
// transform: translateX(100%) !important;
background: #1de9b6;
@include mobile {
height: 3px;
}
}
.el-tabs__nav {
@include mobile {
display: flex;
flex: 1;
width: 100%;
}
.el-tabs__item.is-active {
color: #ffffff;
}
.el-tabs__item {
color: #7d7d7e;
@include mobile {
display: flex;
flex: 1;
justify-content: center;
align-items: center;
padding: 0;
}
&:hover {
color: #ffffff;
}
}
}
.el-tabs__nav-wrap {
&::after {
height: 0px;
border-bottom: 1px solid #3b3b3c;
}
}
}
// 详情页面的
.details-tabs{
.el-tabs__active-bar {
display: none;
}
.el-tabs__nav {
display: flex;
flex: 1;
@include mobile {
width: auto;
}
.el-tabs__item.is-active {
color: #ffffff;
background: #5834B6;
}
.el-tabs__item {
display: flex;
flex: 1;
padding: 20px 40px !important;
background: #2B2B2C;
height: auto;
width: auto;
color: #ffffff;
font-size: 16px;
font-weight: 500;
@include mobile{
padding: 10px 24px !important;
}
&:hover {
color: #ffffff;
}
}
}
.el-tabs__nav-wrap {
&::after {
height: 0px;
border-bottom: 1px solid #3b3b3c;
}
}
}

93
src/pages/TableBlock/index.vue

@ -0,0 +1,93 @@
<template>
<div class="bg-black desktop:pt-[76px] mobile:pt-[39px]">
<!-- pc端显示 -->
<div class="mobile:hidden">
<div class="flex flex-row px-[120px] justify-between items-center">
<div class="flex flex-1 justify-start items-center">
<img :src="url" class="w-[60px] h-[33px]" />
<span class="text-[34px] font-semibold text-white ml-[11.5px]"
>MetaForce Scan</span
>
</div>
<div class="flex flex-1 h-[52px] justify-end items-center">
<div class="flex flex-1 max-w-[554px]">
<el-input
v-model="input"
class="bg-black h-[52px] pl-[33px] text-[12px] rounded-[100px] overflow-hidden hp-input-wrapper"
placeholder="Search by Address/Token symbol/Name/Transaction hash/Bock number"
:prefix-icon="Search"
:input-style="{ background: '#262626' }"
/>
</div>
</div>
</div>
<div
class="bg-home-page bg-cover bg-center bg-no-repeat w-[1440px] h-[535.5px]"
></div>
</div>
<!-- 移动端显示 -->
<div class="desktop:hidden">
<div
class="bg-home-page bg-cover bg-center bg-no-repeat w-full h-[219px] pt-[25px]"
>
<div class="flex flex-1 justify-center items-center">
<img :src="url" class="w-[40px] h-[24px]" />
<span class="text-[24px] font-semibold text-white ml-[16px]"
>MetaForce Scan</span
>
</div>
<div class="flex flex-1 h-[40px] justify-center items-center mt-[32px]">
<div class="flex flex-1 px-[20px]">
<el-input
v-model="input"
class="bg-black h-[40px] pl-[15.69px] text-[12px] rounded-[100px] overflow-hidden hp-input-wrapper"
placeholder="Search by Address/Token symbol/Name/Transaction hash/Bock number"
:prefix-icon="Search"
:input-style="{ background: '#262626' }"
/>
</div>
</div>
</div>
</div>
<router-view></router-view>
<Footer />
</div>
</template>
<script lang="ts">
import { defineComponent } from '@vue/runtime-core'
import { Search } from '@element-plus/icons-vue'
import Block from './Block/index.vue'
import Footer from '@src/components/footer.vue'
import Transactions from './Transactions/index.vue'
import Tokens from './Tokens/index.vue'
import type { TabsPaneContext } from 'element-plus'
import * as iconList from '../../assets/Icons/index'
export default defineComponent({
components: {
Search,
Block,
Transactions,
Tokens,
Footer,
},
setup() {
return {
Search: Search,
url: iconList.label,
input: '',
active: 'Block', // tab
}
},
methods: {
handleClick(tab: TabsPaneContext, event: Event) {
console.log('tab', tab)
},
},
})
</script>
<style lang="scss">
@import './index.scss';
</style>

39
src/routes.ts

@ -0,0 +1,39 @@
import * as VueRouter from 'vue-router'
import HomePage from './pages/HomePage/index.vue'
import TableBlock from './pages/TableBlock/index.vue'
import TableBlockIndex from './pages/TableBlock/Tabs.vue'
import BlockDetails from './pages/TableBlock/Block/details.vue'
import transactDetails from './pages/TableBlock/Transactions/details.vue'
const routes: VueRouter.RouteRecordRaw[] = [
{
path: '/',
component: HomePage,
},
{
path: '/TableBlock',
component: TableBlock,
children: [
{
path: '/TableBlock/index',
component: TableBlockIndex,
},
{
path: '/TableBlock/:id',
component: BlockDetails,
},
{
path: '/TableBlock/tx/:id',
component: transactDetails,
},
],
},
]
const router = VueRouter.createRouter({
// 通过 createWebHistory() 创建 History 模式。
history: VueRouter.createWebHistory(),
routes,
})
export default router

80
src/style.scss

@ -0,0 +1,80 @@
:root {
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
font-size: 16px;
line-height: 24px;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
// margin: 0;
// display: flex;
// place-items: center;
// min-width: 320px;
// min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
.card {
padding: 2em;
}
#app {
max-width: 1440px;
margin: 0 auto;
padding: 0;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}

7
src/vite-env.d.ts

@ -0,0 +1,7 @@
/// <reference types="vite/client" />
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}

41
tailwind.config.cjs

@ -0,0 +1,41 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
purge: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
content: [],
theme: {
extend: {
screens: {
mobile: {
max: '1439px',
},
// @media (min-width: 375px) { ... }
desktop: '1440px',
// @media (min-width: 1440px) { ... }
},
colors: {
'black-19191A': '#19191A',
'black-272728': '#272728',
'black-006': 'rgba(255, 255, 255, 0.06)',
'black-3B3B3C': '#3B3B3C',
'black-2B2B2C': '#2B2B2C',
'gray-303031': '#303031',
'gray-969697': '#969697',
'gray-BBB': '#BBBBBB',
'gray-7D7D7E': '#7D7D7E',
'gray-C1C0C0': '#C1C0C0',
'green-1DE9B6': '#1DE9B6',
'green-2EAA7D': '#2EAA7D',
'blue-65B5FF': '#65B5FF',
'red-C4403E': '#C4403E',
},
flex: {
half: '1 1 50%',
},
},
screens: {},
backgroundImage: {
'home-page': "url('/src/assets/bg/homepage-topbg.png')",
},
},
plugins: [],
}

22
tsconfig.json

@ -0,0 +1,22 @@
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"moduleResolution": "Node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["ESNext", "DOM"],
"skipLibCheck": true,
"baseUrl": ".",
"paths": {
"@src/*": ["src/*"]
}
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }]
}

9
tsconfig.node.json

@ -0,0 +1,9 @@
{
"compilerOptions": {
"composite": true,
"module": "ESNext",
"moduleResolution": "Node",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}

31
vite.config.ts

@ -0,0 +1,31 @@
import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import vue from '@vitejs/plugin-vue'
import path from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
resolve: {
alias: {
vue: 'vue/dist/vue.esm-bundler.js',
'@src': path.resolve(__dirname, './src'),
},
},
css: {
preprocessorOptions: {
scss: {
additionalData: `@import "/mixin.scss";`,
},
},
},
})

12
vue.config.js

@ -0,0 +1,12 @@
// import path from 'path'
module.exports = {
// pluginOptions: {
// 'style-resources-loader': {
// preProcessor: 'scss',
// patterns: [
// // 路径根据具体需求更改
// path.resolve(__dirname, './mixin.scss'),
// ],
// },
// },
}

1719
yarn.lock

File diff suppressed because it is too large
Loading…
Cancel
Save