Ver código fonte

二次重构完成

skyfffire 3 anos atrás
pai
commit
40e5f9d22b

+ 14 - 67
src/App.vue

@@ -2,54 +2,20 @@
   <v-app>
     <div v-title data-title="EthMevTools"></div>
 
-    <v-app-bar
-      app
-      elevation="1"
-    >
+    <v-app-bar app elevation="1">
       <div class="d-flex align-center">
-        <v-img
-          alt="Logo"
-          class="shrink mr-2"
-          contain
-          src="./assets/logo-ether.png"
-          transition="scale-transition"
-          width="180"
-        />
+        <v-img contain
+               alt="Logo" class="shrink mr-2" src="./assets/logo-ether.png" transition="scale-transition" width="180" />
       </div>
 
-      <v-tabs
-        v-model="tab"
-        v-if="calcPwdMD5() === pwdMD5"
-      >
-        <v-tab
-            key="pending"
-        >
-          Pending
-        </v-tab>
-        <v-tab
-          key="history"
-        >
-          History
-        </v-tab>
-<!--        <v-tab-->
-<!--            key="my"-->
-<!--        >-->
-<!--          我的交易-->
-<!--        </v-tab>-->
-<!--        <v-tab-->
-<!--            key="config"-->
-<!--        >-->
-<!--          参数配置-->
-<!--        </v-tab>-->
+      <v-tabs v-if="calcPwdMD5() === pwdMD5" v-model="tab">
+        <v-tab key="pending">Pending</v-tab>
+        <v-tab key="history">History</v-tab>
       </v-tabs>
 
       <v-spacer></v-spacer>
 
-      <v-btn
-        href="https://etherscan.io/"
-        target="_blank"
-        text
-      >
+      <v-btn text href="https://etherscan.io/" target="_blank">
         <span class="mr-2">Etherscan</span>
         <v-icon>mdi-open-in-new</v-icon>
       </v-btn>
@@ -57,38 +23,22 @@
 
     <v-main>
       <!--   密码测试   -->
-      <v-tabs-items
-        v-model="tab"
-        v-if="calcPwdMD5() !== pwdMD5"
-      >
+      <v-tabs-items v-if="calcPwdMD5() !== pwdMD5" v-model="tab">
         <v-container>
           <v-row>
-            <v-col cols="4">
-            </v-col>
-            <v-col cols="4">
-              <v-img src="./assets/banner.svg"></v-img>
-            </v-col>
+            <v-col cols="4"></v-col>
+            <v-col cols="4"><v-img src="./assets/banner.svg"></v-img></v-col>
           </v-row>
           <v-row>
             <v-col cols="3"></v-col>
             <v-col cols="6">
-              <v-text-field
-                v-model="pwd"
-                append-icon="mdi-cloud-search"
-                outlined
-                label="Search Address"
-                type="text"
-                @click:append="jump"
-              ></v-text-field>
+              <v-text-field outlined append-icon="mdi-cloud-search" label="Search Address" type="text" v-model="pwd" @click:append="jump"></v-text-field>
             </v-col>
             <v-col cols="3"></v-col>
           </v-row>
         </v-container>
       </v-tabs-items>
-      <v-tabs-items
-        v-model="tab"
-        v-else
-      >
+      <v-tabs-items v-else v-model="tab">
         <v-tab-item key="pending">
           <Pending></Pending>
         </v-tab-item>
@@ -102,24 +52,21 @@
 
 <script>
 
-import History from "@/components/History";
-import Pending from "@/components/Pending";
+import History from '@/components/History'
+import Pending from '@/components/Pending'
 import md5 from 'md5-node'
 
 export default {
   name: 'App',
-
   components: {
     History,
     Pending
   },
-
   data: () => ({
     tab: 'pending',
     pwdMD5: '7f5029bbd4daae18f3ae4cd910f0f4f0',
     pwd: ''
   }),
-
   methods: {
     calcPwdMD5 () {
       return md5(this.pwd)

+ 72 - 230
src/components/History.vue

@@ -1,235 +1,39 @@
 <template>
-  <v-card
-      elevation="1"
-  >
-    <v-container>
-      <v-row>
-        <!-- block过滤 -->
-        <v-col cols="18" md="2">
-          <v-text-field required label="BlockNumber" v-model="query.block" />
-        </v-col>
+  <v-card elevation="1">
+    <!-- 顶部组件 -->
+    <Top :query='query' :page='page' :table='table'></Top>
 
-        <!-- hash过滤 -->
-        <v-col cols="18" md="2">
-          <v-text-field required label="Hash" v-model="query.hash" />
-        </v-col>
-
-        <!-- data过滤 -->
-        <v-col cols="18" md="6">
-          <v-text-field required label="Data" v-model="query.dataVague" />
-        </v-col>
-
-        <!-- 搜索按钮 -->
-        <v-col cols="18" md="1">
-          <v-btn outlined x-large tile color="primary" @click="generateHistoryData">
-            <v-icon>mdi-cloud-search-outline</v-icon>
-          </v-btn>
-        </v-col>
-      </v-row>
-    </v-container>
-
-    <!-- 表格组件 -->
-    <v-card elevation="0">
-      <!-- 表格上功能区 -->
-      <v-card-title>
-        <v-container id="dataTableHeader">
-          <v-row>
-            <v-col cols="4">
-              History Data
-            </v-col>
-            <v-col cols="8">
-              <v-text-field hide-details single-line label="Local Search" append-icon="mdi-magnify" v-model="search"/>
-            </v-col>
-          </v-row>
-
-          <v-row>
-            <v-col cols="12">
-              Block: {{ showBlock }}
-            </v-col>
-          </v-row>
-        </v-container>
-      </v-card-title>
-
-      <!-- 表格主体 -->
-      <v-data-table calculate-widths multi-sort group-desc
-                    group-by="block"
-                    :headers="headers" :items="tableData" :search="search" :items-per-page="200" :loading="loading"
-                    :sort-by="['block', 'index']" :sort-desc="[true, false]">
-        <!-- 操作区 -->
-        <template v-slot:item.option="{ item }">
-          <div @mouseenter="changeShowBlock(item, false)">
-            <v-row>
-              <v-col cols="5">
-                <v-btn icon elevation="0" color="red" large @click="deleteByHash(item.hash)">
-                  <v-icon large>mdi-delete-forever-outline</v-icon>
-                </v-btn>
-              </v-col>
-            </v-row>
-          </div>
-        </template>
-        <!-- Block -->
-        <template v-slot:item.block="{ item }">
-          <div @mouseenter="changeShowBlock(item, false)">
-            {{ item.block }}
-          </div>
-        </template>
-        <!-- Hash -->
-        <template v-slot:item.hash="{ item }">
-          <v-chip label target="_blank" :href="'https://www.oklink.com/en/ethw/tx/' + item.hash">
-            {{ hashKit.head5(item.hash) + '..' }}
-          </v-chip>
-        </template>
-        <!-- From -->
-        <template v-slot:item.from="{ item }">
-          <v-chip label color="green lighten-3" target="_blank" @click="httpKit.jumpToEthw(item.from)">
-            {{ hashKit.headAndEnd2(item.from) }}
-          </v-chip>
-        </template>
-        <!-- to -->
-        <template v-slot:item.to="{ item }">
-          <v-chip v-if="!item.toName" label color="indigo lighten-4"  @click="httpKit.jumpToEthw(item.to)">
-            {{ hashKit.headAndEnd2(item.to) }}
-          </v-chip>
-          <v-chip v-else label color="indigo lighten-4" @click="httpKit.jumpToEthw(item.to)">
-            {{ item.toName }}
-          </v-chip>
-        </template>
-        <template v-slot:item.type="{ item }">
-          <div v-if="item.type !== undefined && item.type !== ''">
-            {{ item.type }}
-          </div>
-          <div v-else>
-            [type]
-          </div>
-        </template>
-        <template v-slot:item.index="{ item }">
-          <div v-if="item.index !== undefined">
-            {{ item.index }}
-          </div>
-          <div v-else>
-            [index]
-          </div>
-        </template>
-        <template v-slot:item.state="{ item }">
-          <div v-if="item.state !== undefined">
-            {{ item.state }}
-          </div>
-          <div v-else>
-            [state]
-          </div>
-        </template>
-        <template v-slot:item.mev="{ item }">
-          <div v-if="item.mev !== undefined">
-            {{ item.mev }}
-          </div>
-          <div v-else>
-            [mev]
-          </div>
-        </template>
-        <template v-slot:item.pending="{ item }">
-          <div v-if="item.pending !== undefined">
-            {{ item.pending }}
-          </div>
-          <div v-else>
-            [pending]
-          </div>
-        </template>
-        <!--tradeInfo-->
-        <template v-slot:item.tradeInfo="{ item }">
-          <TradeInfo :item="item"></TradeInfo>
-        </template>
-      </v-data-table>
-    </v-card>
-
-    <v-snackbar color="blue-grey" timeout="100000" v-model="blockSnackbar">
-      block: {{ showBlock }}
-
-      <template v-slot:action="{ attrs }">
-        <v-btn text color="white" v-bind="attrs" @click="blockSnackbar = false">Close</v-btn>
-      </template>
-    </v-snackbar>
+    <!-- 中间表格组件 -->
+    <Table :query='query' :page='page' :table='table'></Table>
   </v-card>
 </template>
 
 <script>
-  import NumKit from '@/plugins/kit/NumKit'
-  import HashKit from '@/plugins/kit/HashKit'
-  import HttpKit from '@/plugins/kit/HttpKit'
-  import EthMev from '@/plugins/model/EthMev'
-  import TradeInfo from '@/components/history/TradeInfo';
-
-  export default {
-    name: 'History',
-    components: { TradeInfo },
-    methods: {
-      // 获取数据
-      async generateHistoryData () {
-        this.tableData.length = 0
-
-        this.loading = true
-        const rst = await EthMev.getEthMevData(this.query.block, this.query.hash, this.query.dataVague)
-        this.loading = false
-
-        if (!rst.data.state) {
-          this.$msgkit.error(rst.data.msg)
-
-          return
-        }
-
-        this.$msgkit.success(rst.data.msg)
-        this.tableData = rst.data.data
-
-        this.tableData.map(function (one) {
-          try {
-            let dataObj = one.dataObj
-
-            one.tradeInfo = dataObj.tradeInfo
-            one.from = dataObj.fromAdd
-            one.to = dataObj.toAdd
-            one.gasPrice = NumKit._N(parseInt(dataObj.gasPrice) / (10 ** 9), 2)
-            one.index = dataObj.index
-            one.type = dataObj.type
-            one.state = dataObj.status
-            one.pending = dataObj.pending
-          } catch (e) {
-            one.tradeInfo = []
-          }
-        })
-      },
-      async deleteByHash(hash_code) {
-        if (confirm('要删吗?\n' + hash_code)) {
-          const rst = await EthMev.deleteByHash(hash_code)
-
-          if (rst.data.state) {
-            this.$msgkit.success(rst.data.msg)
-
-            await this.pullData()
-          } else {
-            this.$msgkit.error(rst.data.msg)
-          }
-        }
-      },
-      logInfo (info) {
-        console.log(info)
-      },
-      changeShowBlock (item, openSnackbar) {
-        if (openSnackbar) this.blockSnackbar = true
-        this.showBlock = item.block
-      }
+import Top from '@/components/viewer/Top'
+import Table from '@/components/viewer/Table'
+import EthMev from "@/plugins/model/EthMev";
+import NumKit from "@/plugins/kit/NumKit";
+
+export default {
+  name: 'History',
+  components: {Top, Table},
+  data: () => ({
+    query: {
+      block: '',
+      hash: '',
+      dataVague: ''
     },
-
-    data: () => ({
-      hashKit: HashKit,
-      httpKit: HttpKit,
-      query: {
-        block: '',
-        hash: '',
-        dataVague: ''
-      },
-      blockSnackbar: false,
+    page: {
+      name: 'History Page'
+    },
+    table: {
       search: '',
-      showBlock: 0,
       loading: false,
+      groupBy: 'block',
+      sortBy: ['block', 'index'],
+      sortDesc: [true, false],
+      pageSize: 200,
+      data: [],
       headers: [
         { text: "Option", value: 'option', width: '7%' },
         { text: 'Block', value: 'block' },
@@ -243,15 +47,54 @@
         { text: 'Mev', value: 'mev', width: '3%' },
         { text: 'Pending', value: 'pending', width: '7%' },
         { text: 'TradeInfo', value: 'tradeInfo'}
-      ],
-      history: {"data":[{"t":"0x8a2a17e7adb6cbf6635380a35c04c01db473ed5ca919706f1c492d3aa1d9f1a9","fm":"0x6ff6f16a2459114fad74eed1604b402b97b02717","hs":"0x8a2a17e7adb6cbf6635380a35c04c01db473ed5ca919706f1c492d3aa1d9f1a9","state":"ok","ts":1602503469,"o":"{'type': 'NO TOKEN', 'intoken': 'WETH', 'outtoken': false, 'inamount': 0.314674952033383, 'outamount': 48953401866254456333, 'symbol': false, 'gas': 56.100000233, 'profit': 0, 'balance': 0, 'stocks': 0, 'decimals': 18, 'symbolAddress': '0x054f76beed60ab6dbeb23502178c52d6c5debe40', 'pairAddress': false, 'from': '0x6ff6f16a2459114fad74eed1604b402b97b02717', 'to': '0x8a2a17e7adb6cbf6635380a35c04c01db473ed5ca919706f1c492d3aa1d9f1a9', 'hs': '0x8a2a17e7adb6cbf6635380a35c04c01db473ed5ca919706f1c492d3aa1d9f1a9'}"}],"count":1,"state":"ok"},
-      tableData: []
-    }),
+      ]
+    },
+  }),
+  methods: {
+    // 获取数据
+    async generateTableData() {
+      this.table.data.length = 0
 
-    async mounted () {
-      await this.generateHistoryData()
+      this.table.loading = true
+      const rst = await EthMev.getEthMevData(this.query.block, this.query.hash, this.query.dataVague)
+      this.table.loading = false
+
+      if (!rst.data.state) {
+        this.$msgkit.error(rst.data.msg)
+
+        return
+      }
+
+      this.$msgkit.success(rst.data.msg)
+      this.table.data = rst.data.data
+
+      this.table.data.map(function (one) {
+        try {
+          let dataObj = one.dataObj
+
+          one.tradeInfo = dataObj.tradeInfo
+          one.from = dataObj.fromAdd
+          one.to = dataObj.toAdd
+          one.gasPrice = NumKit._N(parseInt(dataObj.gasPrice) / (1E9), 2)
+          one.index = dataObj.index
+          one.type = dataObj.type
+          one.state = dataObj.status
+          one.pending = dataObj.pending
+        } catch (e) {
+          one.tradeInfo = []
+        }
+      })
+    }
+  },
+  provide() {
+    return {
+      generateTableData: this.generateTableData
     }
+  },
+  async mounted () {
+    await this.generateTableData()
   }
+}
 </script>
 
 <style>
@@ -269,7 +112,6 @@ thead.v-data-table-header {
   bottom: 0 !important;
   z-index: 999;
   background-color: rgba(255, 255, 255, 255);
-  width: 95%;
   border-top: grey 1px solid;
 }
 div.tokenName {

+ 58 - 214
src/components/Pending.vue

@@ -1,174 +1,63 @@
 <template>
-  <v-card
-      elevation="1"
-  >
-    <v-container>
-      <v-row>
-        <!-- block过滤 -->
-        <v-col cols="18" md="2">
-          <v-text-field required label="BlockNumber" v-model="query.block" />
-        </v-col>
+  <v-card elevation="1">
+    <!-- 顶部组件 -->
+    <Top :query='query' :page='page' :table='table'></Top>
 
-        <!-- hash过滤 -->
-        <v-col cols="18" md="2">
-          <v-text-field required label="Hash" v-model="query.hash" />
-        </v-col>
-
-        <!-- data过滤 -->
-        <v-col cols="18" md="6">
-          <v-text-field required label="Data" v-model="query.dataVague" />
-        </v-col>
-
-        <!-- 搜索按钮 -->
-        <v-col cols="18" md="1">
-          <v-btn outlined x-large tile color="primary" @click="generateHistoryData">
-            <v-icon>mdi-cloud-search-outline</v-icon>
-          </v-btn>
-        </v-col>
-      </v-row>
-    </v-container>
-
-    <!-- 表格组件 -->
-    <v-card elevation="0">
-      <!-- 表格上功能区 -->
-      <v-card-title>
-        <v-container id="dataTableHeader">
-          <v-row>
-            <v-col cols="4">
-              Pending Data
-            </v-col>
-            <v-col cols="8">
-              <v-text-field hide-details single-line label="Local Search" append-icon="mdi-magnify" v-model="search"/>
-            </v-col>
-          </v-row>
-
-          <v-row>
-            <v-col cols="12">
-              Block: {{ showBlock }}
-            </v-col>
-          </v-row>
-        </v-container>
-      </v-card-title>
-
-      <!-- 表格主体 -->
-      <v-data-table calculate-widths multi-sort
-                    group-by="block"
-                    :headers="headers" :items="tableData" :search="search" :items-per-page="200" :loading="loading"
-                    :sort-by="['block', 'gasPrice', 'pending']" :sort-desc="[false, true, false]">
-        <!-- 操作区 -->
-        <template v-slot:item.option="{ item }">
-          <div @mouseenter="changeShowBlock(item, false)">
-            <v-row>
-              <v-col cols="5">
-                <v-btn icon elevation="0" color="red" large @click="deleteByHash(item.hash)">
-                  <v-icon large>mdi-delete-forever-outline</v-icon>
-                </v-btn>
-              </v-col>
-            </v-row>
-          </div>
-        </template>
-        <!-- Block -->
-        <template v-slot:item.block="{ item }">
-          <div @mouseenter="changeShowBlock(item, false)">
-            {{ item.block }}
-          </div>
-        </template>
-        <!-- Hash -->
-        <template v-slot:item.hash="{ item }">
-          <v-chip label target="_blank" :href="'https://www.oklink.com/en/ethw/tx/' + item.hash">
-            {{ hashKit.head5(item.hash) + '..' }}
-          </v-chip>
-        </template>
-        <!-- From -->
-        <template v-slot:item.from="{ item }">
-          <v-chip label color="green lighten-3" target="_blank" @click="httpKit.jumpToEthw(item.from)">
-            {{ hashKit.headAndEnd2(item.from) }}
-          </v-chip>
-        </template>
-        <!-- to -->
-        <template v-slot:item.to="{ item }">
-          <v-chip v-if="!item.toName" label color="indigo lighten-4"  @click="httpKit.jumpToEthw(item.to)">
-            {{ hashKit.headAndEnd2(item.to) }}
-          </v-chip>
-          <v-chip v-else label color="indigo lighten-4" @click="httpKit.jumpToEthw(item.to)">
-            {{ item.toName }}
-          </v-chip>
-        </template>
-        <template v-slot:item.type="{ item }">
-          <div v-if="item.type !== undefined && item.type !== ''">
-            {{ item.type }}
-          </div>
-          <div v-else>
-            [type]
-          </div>
-        </template>
-        <template v-slot:item.index="{ item }">
-          <div v-if="item.index !== undefined">
-            {{ item.index }}
-          </div>
-          <div v-else>
-            [index]
-          </div>
-        </template>
-        <template v-slot:item.state="{ item }">
-          <div v-if="item.state !== undefined">
-            {{ item.state }}
-          </div>
-          <div v-else>
-            [state]
-          </div>
-        </template>
-        <template v-slot:item.mev="{ item }">
-          <div v-if="item.mev !== undefined">
-            {{ item.mev }}
-          </div>
-          <div v-else>
-            [mev]
-          </div>
-        </template>
-        <template v-slot:item.pending="{ item }">
-          <div v-if="item.pending !== undefined">
-            {{ item.pending }}
-          </div>
-          <div v-else>
-            [pending]
-          </div>
-        </template>
-        <!--tradeInfo-->
-        <template v-slot:item.tradeInfo="{ item }">
-          <TradeInfo :item="item"></TradeInfo>
-        </template>
-      </v-data-table>
-    </v-card>
-
-    <v-snackbar color="blue-grey" timeout="100000" v-model="blockSnackbar">
-      block: {{ showBlock }}
-
-      <template v-slot:action="{ attrs }">
-        <v-btn text color="white" v-bind="attrs" @click="blockSnackbar = false">Close</v-btn>
-      </template>
-    </v-snackbar>
+    <!-- 中间表格组件 -->
+    <Table :query='query' :page='page' :table='table'></Table>
   </v-card>
 </template>
 
 <script>
-import NumKit from '@/plugins/kit/NumKit'
-import HashKit from '@/plugins/kit/HashKit'
-import HttpKit from '@/plugins/kit/HttpKit'
-import EthMev from '@/plugins/model/EthMev'
-import TradeInfo from '@/components/history/TradeInfo';
+import Top from '@/components/viewer/Top'
+import Table from '@/components/viewer/Table'
+import EthMev from "@/plugins/model/EthMev";
+import NumKit from "@/plugins/kit/NumKit";
 
 export default {
   name: 'Pending',
-  components: {TradeInfo},
+  components: {Top, Table},
+  data: () => ({
+    query: {
+      block: '',
+      hash: '',
+      dataVague: ''
+    },
+    page: {
+      name: 'Pending Page'
+    },
+    table: {
+      search: '',
+      loading: false,
+      groupBy: 'block',
+      sortBy: ['block', 'gasPrice', 'pending'],
+      sortDesc: [false, true, false],
+      pageSize: 200,
+      data: [],
+      headers: [
+        {text: "Option", value: 'option'},
+        {text: 'Block', value: 'block'},
+        {text: 'Hash', value: 'hash'},
+        {text: 'From', value: 'from'},
+        {text: 'To', value: 'to'},
+        {text: 'GasPrice', value: 'gasPrice'},
+        {text: 'Type', value: 'type'},
+        {text: 'Index', value: 'index'},
+        {text: 'State', value: 'state'},
+        {text: 'Mev', value: 'mev'},
+        {text: 'Pending', value: 'pending'},
+        {text: 'TradeInfo', value: 'tradeInfo'}
+      ]
+    }
+  }),
   methods: {
     // 获取数据
-    async generateHistoryData() {
-      this.tableData.length = 0
+    async generateTableData() {
+      this.table.data.length = 0
 
-      this.loading = true
+      this.table.loading = true
       const rst = await EthMev.getEthMevPendingData(this.query.block, this.query.hash, this.query.dataVague)
-      this.loading = false
+      this.table.loading = false
 
       if (!rst.data.state) {
         this.$msgkit.error(rst.data.msg)
@@ -177,16 +66,16 @@ export default {
       }
 
       this.$msgkit.success(rst.data.msg)
-      this.tableData = rst.data.data
+      this.table.data = rst.data.data
 
-      this.tableData.map(function (one) {
+      this.table.data.map(function (one) {
         try {
           let dataObj = one.dataObj
 
           one.tradeInfo = dataObj.tradeInfo
           one.from = dataObj.fromAdd
           one.to = dataObj.toAdd
-          one.gasPrice = NumKit._N(parseInt(dataObj.gasPrice) / (10 ** 9), 2)
+          one.gasPrice = NumKit._N(parseInt(dataObj.gasPrice) / (1E9), 2)
           one.index = dataObj.index
           one.type = dataObj.type
           one.state = dataObj.status
@@ -195,60 +84,15 @@ export default {
           one.tradeInfo = []
         }
       })
-    },
-    async deleteByHash(hash_code) {
-      if (confirm('要删吗?\n' + hash_code)) {
-        const rst = await EthMev.deleteByHash(hash_code)
-
-        if (rst.data.state) {
-          this.$msgkit.success(rst.data.msg)
-
-          await this.pullData()
-        } else {
-          this.$msgkit.error(rst.data.msg)
-        }
-      }
-    },
-    logInfo(info) {
-      console.log(info)
-    },
-    changeShowBlock(item, openSnackbar) {
-      if (openSnackbar) this.blockSnackbar = true
-      this.showBlock = item.block
     }
   },
-
-  data: () => ({
-    hashKit: HashKit,
-    httpKit: HttpKit,
-    query: {
-      block: '',
-      hash: '',
-      dataVague: ''
-    },
-    blockSnackbar: false,
-    search: '',
-    showBlock: 0,
-    loading: false,
-    headers: [
-      {text: "Option", value: 'option'},
-      {text: 'Block', value: 'block'},
-      {text: 'Hash', value: 'hash'},
-      {text: 'From', value: 'from'},
-      {text: 'To', value: 'to'},
-      {text: 'GasPrice', value: 'gasPrice'},
-      {text: 'Type', value: 'type'},
-      {text: 'Index', value: 'index'},
-      {text: 'State', value: 'state'},
-      {text: 'Mev', value: 'mev'},
-      {text: 'Pending', value: 'pending'},
-      // { text: 'TradeInfo', value: 'tradeInfo'}
-    ],
-    tableData: []
-  }),
-
-  async mounted() {
-    await this.generateHistoryData()
+  provide() {
+    return {
+      generateTableData: this.generateTableData
+    }
+  },
+  async mounted () {
+    await this.generateTableData()
   }
 }
 </script>
@@ -271,7 +115,7 @@ thead.v-data-table-header {
   bottom: 0 !important;
   z-index: 999;
   background-color: rgba(255, 255, 255, 255);
-  width: 95%;
+  width: 96.35%;
   border-top: grey 1px solid;
 }
 

+ 144 - 0
src/components/viewer/Table.vue

@@ -0,0 +1,144 @@
+<template>
+  <v-card elevation="0">
+    <!-- 表格上功能区 -->
+    <v-card-title>
+      <v-container id="dataTableHeader">
+        <v-row>
+          <v-col cols="4">
+            {{ page.name }}
+          </v-col>
+          <v-col cols="8">
+            <v-text-field hide-details single-line label="Local Search" append-icon="mdi-magnify" v-model="table.search"/>
+          </v-col>
+        </v-row>
+      </v-container>
+    </v-card-title>
+
+    <!-- 表格主体 -->
+    <v-data-table calculate-widths multi-sort
+                  :group-by="table.groupBy"
+                  :headers="table.headers" :items="table.data" :search="table.search" :loading="table.loading"
+                  :items-per-page="table.pageSize"
+                  :sort-by="table.sortBy" :sort-desc="table.sortDesc">
+      <!-- 操作区 -->
+      <template v-slot:item.option="{ item }">
+        <div>
+          <v-row>
+            <v-col cols="5">
+              <v-btn icon elevation="0" color="red" large @click="deleteByHash(item.hash)">
+                <v-icon large>mdi-delete-forever-outline</v-icon>
+              </v-btn>
+            </v-col>
+          </v-row>
+        </div>
+      </template>
+      <!-- Block -->
+      <template v-slot:item.block="{ item }">
+        <div>
+          {{ item.block }}
+        </div>
+      </template>
+      <!-- Hash -->
+      <template v-slot:item.hash="{ item }">
+        <v-chip label target="_blank" :href="'https://www.oklink.com/en/ethw/tx/' + item.hash">
+          {{ hashKit.head5(item.hash) + '..' }}
+        </v-chip>
+      </template>
+      <!-- From -->
+      <template v-slot:item.from="{ item }">
+        <v-chip label color="green lighten-3" target="_blank" @click="httpKit.jumpToEthw(item.from)">
+          {{ hashKit.headAndEnd2(item.from) }}
+        </v-chip>
+      </template>
+      <!-- to -->
+      <template v-slot:item.to="{ item }">
+        <v-chip v-if="!item.toName" label color="indigo lighten-4"  @click="httpKit.jumpToEthw(item.to)">
+          {{ hashKit.headAndEnd2(item.to) }}
+        </v-chip>
+        <v-chip v-else label color="indigo lighten-4" @click="httpKit.jumpToEthw(item.to)">
+          {{ item.toName }}
+        </v-chip>
+      </template>
+      <template v-slot:item.type="{ item }">
+        <div v-if="item.type !== undefined && item.type !== ''">
+          {{ item.type }}
+        </div>
+        <div v-else>
+          [type]
+        </div>
+      </template>
+      <template v-slot:item.index="{ item }">
+        <div v-if="item.index !== undefined">
+          {{ item.index }}
+        </div>
+        <div v-else>
+          [index]
+        </div>
+      </template>
+      <template v-slot:item.state="{ item }">
+        <div v-if="item.state !== undefined">
+          {{ item.state }}
+        </div>
+        <div v-else>
+          [state]
+        </div>
+      </template>
+      <template v-slot:item.mev="{ item }">
+        <div v-if="item.mev !== undefined">
+          {{ item.mev }}
+        </div>
+        <div v-else>
+          [mev]
+        </div>
+      </template>
+      <template v-slot:item.pending="{ item }">
+        <div v-if="item.pending !== undefined">
+          {{ item.pending }}
+        </div>
+        <div v-else>
+          [pending]
+        </div>
+      </template>
+      <!--tradeInfo-->
+      <template v-slot:item.tradeInfo="{ item }">
+        <TradeInfo :item="item"></TradeInfo>
+      </template>
+    </v-data-table>
+  </v-card>
+</template>
+
+<script>
+import TradeInfo from '@/components/viewer/table/TradeInfo'
+import EthMev from '@/plugins/model/EthMev'
+import HashKit from '@/plugins/kit/HashKit'
+import HttpKit from '@/plugins/kit/HttpKit'
+
+export default {
+  name: 'Table',
+  components: {TradeInfo},
+  props: ['query', 'page', 'table'],
+  data: () => ({
+    hashKit: HashKit,
+    httpKit: HttpKit,
+  }),
+  methods: {
+    async deleteByHash(hash_code) {
+      if (confirm('要删吗?\n' + hash_code)) {
+        // const rst = await EthMev.deleteByHash(hash_code)
+        //
+        // if (rst.data.state) {
+        //   this.$msgkit.success(rst.data.msg)
+        //
+        //   await this.pullData()
+        // } else {
+        //   this.$msgkit.error(rst.data.msg)
+        // }
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

+ 44 - 0
src/components/viewer/Top.vue

@@ -0,0 +1,44 @@
+<template>
+  <v-container>
+    <v-row>
+      <!-- block过滤 -->
+      <v-col cols="18" md="2">
+        <v-text-field required label="BlockNumber" v-model="query.block" />
+      </v-col>
+
+      <!-- hash过滤 -->
+      <v-col cols="18" md="2">
+        <v-text-field required label="Hash" v-model="query.hash" />
+      </v-col>
+
+      <!-- data过滤 -->
+      <v-col cols="18" md="6">
+        <v-text-field required label="Data" v-model="query.dataVague" />
+      </v-col>
+
+      <!-- 搜索按钮 -->
+      <v-col cols="18" md="1">
+        <v-btn outlined x-large tile color="primary" @click="generateTableDataAgain">
+          <v-icon>mdi-cloud-search-outline</v-icon>
+        </v-btn>
+      </v-col>
+    </v-row>
+  </v-container>
+</template>
+
+<script>
+export default {
+  name: 'Top',
+  props: ['query', 'page', 'table'],
+  inject: ['generateTableData'],
+  methods: {
+    async generateTableDataAgain() {
+      await this.generateTableData()
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

+ 18 - 35
src/components/history/TradeInfo.vue → src/components/viewer/table/TradeInfo.vue

@@ -4,43 +4,33 @@
       <div v-for="trade in item.tradeInfo">
         <v-row>
           <!--token symbol-->
-          <v-chip label
-                  class="ma-2 tradeLabel"
-                  @click="httpKit.jumpToEthw(trade.token, 'token')"
-                  v-if="!trade.tokenSymbol">
+          <v-chip v-if="!trade.tokenSymbol"
+                  label class="ma-2 tradeLabel" @click="httpKit.jumpToEthw(trade.token, 'token')">
             <!-- 没有名字的 -->
             <div class="tokenName">{{ hashKit.headAndEnd2(trade.token) }}</div>
             <div class="tokenAmount">{{ numKit._N(trade.amount, 4) }} </div>
           </v-chip>
-          <v-chip label
-                  :color="hashKit.generateColorByHash(trade.token)"
-                  class="ma-2 tradeLabel"
-                  @click="httpKit.jumpToEthw(trade.token, 'token')"
-                  v-else>
+          <v-chip v-else
+                  label class="ma-2 tradeLabel" :color="hashKit.generateColorByHash(trade.token)"
+                  @click="httpKit.jumpToEthw(trade.token, 'token')">
             <!-- 有名字的和Ethereum/EthereumPow -->
             <div class="tokenName">{{ trade.tokenSymbol }}</div>
             <div class="tokenAmount">{{ numKit._N(trade.amount, 4) }}</div>
           </v-chip>
           <!--from-->
           <div>
-            <v-chip label
-                    class="ma-2" color="green lighten-3"
-                    @click="httpKit.jumpToEthw(trade.from)"
-                    v-if="trade.from === item.from">
+            <v-chip v-if="trade.from === item.from"
+                    label class="ma-2" color="green lighten-3" @click="httpKit.jumpToEthw(trade.from)">
               {{ hashKit.headAndEnd2(trade.from) }}
             </v-chip>
-            <v-chip label
-                    class="ma-2" color="indigo lighten-4"
-                    @click="httpKit.jumpToEthw(trade.from)"
-                    v-else-if="trade.from === item.to">
+            <v-chip v-else-if="trade.from === item.to"
+                    label class="ma-2" color="indigo lighten-4" @click="httpKit.jumpToEthw(trade.from)">
               <div v-if="!trade.fromName">{{ hashKit.headAndEnd2(trade.from) }}</div>
               <div v-else>{{ trade.fromName }}</div>
             </v-chip>
-            <v-chip label
-                    class="ma-2"
-                    :color="hashKit.generateColorByHash(trade.from)"
-                    @click="httpKit.jumpToEthw(trade.from)"
-                    v-else>
+            <v-chip v-else
+                    label class="ma-2" :color="hashKit.generateColorByHash(trade.from)"
+                    @click="httpKit.jumpToEthw(trade.from)">
               <div v-if="!trade.fromName">{{ hashKit.headAndEnd2(trade.from) }}</div>
               <div v-else>{{ trade.fromName }}</div>
             </v-chip>
@@ -48,24 +38,17 @@
           <v-icon>mdi-arrow-expand-right</v-icon>
           <!--to-->
           <div>
-            <v-chip label
-                    class="ma-2" color="green lighten-3"
-                    @click="httpKit.jumpToEthw(trade.to)"
-                    v-if="trade.to === item.from">
+            <v-chip v-if="trade.to === item.from"
+                    label class="ma-2" color="green lighten-3" @click="httpKit.jumpToEthw(trade.to)">
               {{ hashKit.headAndEnd2(trade.to) }}
             </v-chip>
-            <v-chip label
-                    class="ma-2" color="indigo lighten-4"
-                    @click="httpKit.jumpToEthw(trade.to)"
-                    v-else-if="trade.to === item.to">
+            <v-chip v-else-if="trade.to === item.to"
+                    label class="ma-2" color="indigo lighten-4" @click="httpKit.jumpToEthw(trade.to)">
               <div v-if="!trade.toName">{{ hashKit.headAndEnd2(trade.to) }}</div>
               <div v-else>{{ trade.toName }}</div>
             </v-chip>
-            <v-chip label
-                    class="ma-2"
-                    :color="hashKit.generateColorByHash(trade.to)"
-                    @click="httpKit.jumpToEthw(trade.to)"
-                    v-else>
+            <v-chip v-else
+                    label class="ma-2" :color="hashKit.generateColorByHash(trade.to)" @click="httpKit.jumpToEthw(trade.to)">
               <div v-if="!trade.toName">{{ hashKit.headAndEnd2(trade.to) }}</div>
               <div v-else>{{ trade.toName }}</div>
             </v-chip>