My.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. <template>
  2. <v-card
  3. elevation="1"
  4. >
  5. <v-container>
  6. <v-row>
  7. <!-- Start Time过滤 -->
  8. <v-col
  9. cols="18"
  10. md="2"
  11. >
  12. <v-text-field
  13. v-model="query.t1_str"
  14. label="Start Time(YYYY/mm/DD HH:MM:SS)"
  15. required
  16. ></v-text-field>
  17. </v-col>
  18. <!-- End Time过滤 -->
  19. <v-col
  20. cols="18"
  21. md="2"
  22. >
  23. <v-text-field
  24. v-model="query.t2_str"
  25. label="End Time(YYYY/mm/DD HH:MM:SS)"
  26. required
  27. ></v-text-field>
  28. </v-col>
  29. <!-- hash过滤 -->
  30. <v-col
  31. cols="18"
  32. md="2"
  33. >
  34. <v-text-field
  35. v-model="query.hs"
  36. label="Hash"
  37. required
  38. ></v-text-field>
  39. </v-col>
  40. <!-- From -->
  41. <v-col
  42. cols="18"
  43. md="2"
  44. >
  45. <v-text-field
  46. v-model="query.fm"
  47. label="From"
  48. required
  49. ></v-text-field>
  50. </v-col>
  51. <!-- To -->
  52. <v-col
  53. cols="18"
  54. md="2"
  55. >
  56. <v-text-field
  57. v-model="query.t"
  58. label="To"
  59. required
  60. ></v-text-field>
  61. </v-col>
  62. <!-- State -->
  63. <v-col
  64. cols="18"
  65. md="1"
  66. >
  67. <v-text-field
  68. v-model="query.state"
  69. label="State"
  70. required
  71. ></v-text-field>
  72. </v-col>
  73. <v-col
  74. cols="18"
  75. md="1"
  76. >
  77. <v-btn outlined tile color="primary" @click="searchData">
  78. <v-icon left>mdi-cloud-search-outline</v-icon>
  79. Search
  80. </v-btn>
  81. </v-col>
  82. </v-row>
  83. </v-container>
  84. <v-card
  85. elevation="0"
  86. >
  87. <v-card-title>
  88. My Data
  89. <v-spacer></v-spacer>
  90. <v-text-field
  91. v-model="search"
  92. append-icon="mdi-magnify"
  93. label="Search"
  94. single-line
  95. hide-details
  96. ></v-text-field>
  97. </v-card-title>
  98. <v-data-table
  99. dense
  100. hide-default-footer
  101. multi-sort
  102. :headers="headers"
  103. :items="tableData"
  104. :search="search"
  105. :items-per-page="10000"
  106. :loading="loading"
  107. :sort-by="['ts', 'block', 'nonce']"
  108. :sort-desc="[true, true, true]"
  109. >
  110. <template v-slot:item.ts="{ item }">
  111. {{ getTime(item.ts) }}
  112. </template>
  113. <!-- Type -->
  114. <template v-slot:item.type="{ item }">
  115. <v-chip small v-if="item.o.type.indexOf('err') !== -1" outlined label color="grey">
  116. <v-icon small left>mdi-filter-remove</v-icon>
  117. {{ item.o.type.split(':')[1] }}
  118. </v-chip>
  119. <v-chip small v-else-if="item.o.type.indexOf('WARN') !== -1" outlined label color="red lighten-2">
  120. <v-icon small left>mdi-alert-circle-outline</v-icon>
  121. {{ item.o.type.split(':')[1] }}
  122. </v-chip>
  123. <v-chip small v-else-if="item.o.type.indexOf('DS:') !== -1" outlined label color="cyan darken-3">
  124. <v-icon small left>mdi-horse-human</v-icon>
  125. {{ item.o.type.split(':')[1] }}
  126. </v-chip>
  127. <v-chip small v-else-if="item.o.type.indexOf('CASH') !== -1" outlined label color="black">
  128. <v-icon small left>mdi-currency-usd</v-icon>
  129. {{ item.o.type.split(':')[1] }}
  130. </v-chip>
  131. <v-chip small v-else-if="item.o.type.indexOf('ZIJI') !== -1" outlined label color="blue">
  132. <v-icon small left>mdi-panda</v-icon>
  133. {{ item.o.type.split(':')[1] }}
  134. </v-chip>
  135. </template>
  136. <!-- Hash -->
  137. <template v-slot:item.hs="{ item }">
  138. <v-tooltip right>
  139. <template v-slot:activator="{ on, attrs }">
  140. <v-btn small :href="'https://etherscan.io/tx/' + item.hs" target="_blank" text v-on="on" v-bind="attrs">{{ getSimpleStr(item.hs) }}</v-btn>
  141. </template>
  142. <span>{{ item.hs }}</span>
  143. </v-tooltip>
  144. </template>
  145. <!-- From -->
  146. <!-- <template v-slot:item.fm="{ item }">-->
  147. <!-- <v-tooltip right>-->
  148. <!-- <template v-slot:activator="{ on, attrs }">-->
  149. <!-- <v-btn :href="'https://etherscan.io/address/' + item.fm" target="_blank" text v-on="on" v-bind="attrs">{{ getSimpleStr(item.fm) }}</v-btn>-->
  150. <!-- </template>-->
  151. <!-- <span>{{ item.fm }}</span>-->
  152. <!-- </v-tooltip>-->
  153. <!-- </template>-->
  154. <!-- Address -->
  155. <template v-slot:item.symbolAddress="{ item }">
  156. <v-tooltip right>
  157. <template v-slot:activator="{ on, attrs }">
  158. <v-btn small :href="'https://etherscan.io/address/' + item.symbolAddress" target="_blank" text v-on="on" v-bind="attrs">{{ getSimpleStr(item.symbolAddress) }}</v-btn>
  159. </template>
  160. <span>{{ item.symbolAddress }}</span>
  161. </v-tooltip>
  162. </template>
  163. <!-- Gas -->
  164. <template v-slot:item.o="{ item }">
  165. {{ item.o.gas }}
  166. </template>
  167. <!-- 利润 -->
  168. <template v-slot:item.profit="{ item }">
  169. {{ item.o.profit }}
  170. </template>
  171. <!-- Block -->
  172. <template v-slot:item.block="{ item }">
  173. {{ item.o.blockNumber }}
  174. </template>
  175. <!-- Nonce -->
  176. <template v-slot:item.nonce="{ item }">
  177. {{ item.o.nonce }}
  178. </template>
  179. <!-- origin -->
  180. <template v-slot:item.origin>
  181. {{ '' }}
  182. </template>
  183. <!-- State -->
  184. <template v-slot:item.state="{ item }">
  185. <v-chip small v-if="item.state === 'ok'" outlined label color="teal"> ok </v-chip>
  186. <v-chip small v-else-if="item.state === 'pending'" outlined label color="orange"> {{ item.state }} </v-chip>
  187. <v-chip small v-else-if="item.state === 'fail'" outlined label color="red lighten-3"> {{ item.state }} </v-chip>
  188. <v-chip small v-else-if="item.state === 'cancel'" outlined label color="blue-grey"> {{ item.state }} </v-chip>
  189. </template>
  190. <!-- Amount -->
  191. <template v-slot:item.amount="{ item }">
  192. <div v-if="!item.o.intoken">
  193. <v-chip small outlined color="red accent-1">-{{ item.o.inamount }}(TOKEN)</v-chip>
  194. >
  195. <v-chip small outlined color="teal lighten-1" @click="jump(item.o.pairAddress)">+{{ item.o.outamount }}({{ item.o.outtoken }})</v-chip>
  196. </div>
  197. <div v-else-if="!item.o.outtoken">
  198. <v-chip small outlined color="red accent-1">-{{ item.o.inamount }}({{ item.o.intoken }})</v-chip>
  199. >
  200. <v-chip small outlined color="teal lighten-1" @click="jump(item.o.pairAddress)">+{{ item.o.outamount }}(TOKEN)</v-chip>
  201. </div>
  202. <div v-else>
  203. <v-chip small outlined color="red accent-1">-{{ item.o.inamount }}({{ item.o.intoken }})</v-chip>
  204. >
  205. <v-chip small outlined color="teal lighten-1" @click="jump(item.o.pairAddress)">+{{ item.o.outamount }}({{ item.o.outtoken }})</v-chip>
  206. </div>
  207. </template>
  208. </v-data-table>
  209. </v-card>
  210. </v-card>
  211. </template>
  212. <script>
  213. import axios from 'axios'
  214. export default {
  215. name: 'History',
  216. methods: {
  217. // 时间戳转换chart时间
  218. getTime (timestamp) {
  219. // 组织日期格式并返回
  220. return this.dateFormat('YYYY-mm-dd HH:MM:SS:sss', new Date(timestamp * 1000))
  221. },
  222. dateFormat(fmt, date) {
  223. let ret;
  224. const opt = {
  225. "Y+": date.getFullYear().toString(), // 年
  226. "m+": (date.getMonth() + 1).toString(), // 月
  227. "d+": date.getDate().toString(), // 日
  228. "H+": date.getHours().toString(), // 时
  229. "M+": date.getMinutes().toString(), // 分
  230. "S+": date.getSeconds().toString(), // 秒
  231. "s+": date.getMilliseconds().toString() // 毫秒
  232. // 有其他格式化字符需求可以继续添加,必须转化成字符串
  233. };
  234. for (let k in opt) {
  235. ret = new RegExp("(" + k + ")").exec(fmt);
  236. if (ret) {
  237. fmt = fmt.replace(ret[1], (ret[1].length === 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
  238. }
  239. }
  240. return fmt;
  241. },
  242. // 最后四位
  243. getSimpleStr (str) {
  244. if (str && str.indexOf('x') !== -1) {
  245. return str.substr(0, 7) + '...' + str.substr(-4)
  246. } else {
  247. return ''
  248. }
  249. },
  250. async getRecord () {
  251. let url = '/data/getRecordByMySelf'
  252. this.loading = true
  253. if (this.searched) {
  254. this.query.t1 = this.query.t1_str ? this.dateToTimestamp(this.query.t1_str) : ''
  255. this.query.t2 = this.query.t2_str ? this.dateToTimestamp(this.query.t2_str) : ''
  256. }
  257. const data = await axios.get(url, { params: this.query })
  258. this.tableData.length = 0
  259. data.data.data.map(function (one) {
  260. one.origin = one.o
  261. one.o = JSON.parse(one.o.replaceAll("'", '"'))
  262. one.blockNumber = one.o.blockNumber
  263. one.gas = one.o.gas
  264. one.nonce = one.o.nonce
  265. one.profit = one.o.profit
  266. one.symbolAddress = one.o.symbolAddress
  267. })
  268. this.tableData = data.data.data
  269. this.loading = false
  270. },
  271. dateToTimestamp (str) {
  272. let [a, b] = str.split(' ')
  273. let [year, month, day] = a.split('/')
  274. let [hour, minute, second] = b.split(':')
  275. return new Date(year, month - 1, day, hour, minute, second).getTime() / 1000
  276. },
  277. jump (pairAddress) {
  278. window.open('https://etherscan.io/address/' + pairAddress)
  279. },
  280. searchData () {
  281. this.searched = true
  282. this.getRecord()
  283. clearInterval(this.intervalID)
  284. }
  285. },
  286. data: () => ({
  287. query: {
  288. t1: '',
  289. t1_str: '',
  290. t2: '',
  291. t2_str: '',
  292. fm: '',
  293. t: '',
  294. state: '',
  295. hs: ''
  296. },
  297. search: '',
  298. loading: false,
  299. headers: [
  300. { text: 'Save Time', value: 'ts' },
  301. // { text: 'Sender', value: 'fm' },
  302. { text: '类型', value: 'type' },
  303. { text: 'Symbol', value: 'symbolAddress' },
  304. { text: '交易数量', value: 'amount' },
  305. { text: '利润', value: 'profit' },
  306. { text: 'Gas', value: 'gas' },
  307. { text: '状态', value: 'state' },
  308. { text: 'BlockNumber', value: 'blockNumber' },
  309. { text: 'Nonce', value: 'nonce' },
  310. { text: 'Hash', value: 'hs' },
  311. { text: ' ', value: 'origin' }
  312. ],
  313. 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"},
  314. tableData: [],
  315. intervalID: 0,
  316. searched: false
  317. }),
  318. mounted() {
  319. this.query.t2_str = '2099/1/1 0:0:0'
  320. this.query.t1_str = this.dateFormat('YYYY/mm/dd HH:MM:SS', new Date(new Date().getTime() - 10 * 60 * 1000))
  321. const app = this
  322. app.query.t1 = parseInt(((new Date().getTime()) / 1000 - 2 * 60) + '')
  323. app.getRecord()
  324. app.intervalID = setInterval(function () {
  325. if (!app.loading) {
  326. app.query.t1 = parseInt(((new Date().getTime()) / 1000) + '')
  327. app.getRecord()
  328. }
  329. }, 10 * 1000)
  330. }
  331. }
  332. </script>
  333. cl