|
|
@@ -1,12 +1,12 @@
|
|
|
<script setup lang="ts">
|
|
|
-import { computed, h, onMounted, reactive, ref, watch } from 'vue'
|
|
|
-import type { DataTableColumns } from 'naive-ui'
|
|
|
-import { ApiCode } from '@/config'
|
|
|
-import { exportVaultTransactions, fetchVaultTransactions } from '@/service/vault'
|
|
|
-import { useVaultStore } from '@/store/vault'
|
|
|
-import type { VaultTransactionItem } from '@/types/vault'
|
|
|
-
|
|
|
-const { t } = useI18n()
|
|
|
+import {computed, h, onMounted, reactive, ref, watch} from 'vue'
|
|
|
+import type {DataTableColumns} from 'naive-ui'
|
|
|
+import {ApiCode} from '@/config'
|
|
|
+import {exportVaultTransactions, fetchVaultTransactions} from '@/service/vault'
|
|
|
+import {useVaultStore} from '@/store/vault'
|
|
|
+import type {VaultTransactionItem} from '@/types/vault'
|
|
|
+
|
|
|
+const {t} = useI18n()
|
|
|
const message = useMessage()
|
|
|
const vault = useVaultStore()
|
|
|
|
|
|
@@ -39,14 +39,29 @@ const filters = reactive<{
|
|
|
senderAddress: string | null
|
|
|
recipientAddress: string | null
|
|
|
timeRange: [number, number] | null
|
|
|
+ blockchain: string | null
|
|
|
+ unit: string | null
|
|
|
}>({
|
|
|
senderLabel: null,
|
|
|
recipientLabel: null,
|
|
|
senderAddress: null,
|
|
|
recipientAddress: null,
|
|
|
timeRange: null,
|
|
|
+ blockchain: null,
|
|
|
+ unit: null,
|
|
|
})
|
|
|
|
|
|
+const blockchainOptions = computed(() => [
|
|
|
+ {label: 'ethereum', value: 'ethereum'},
|
|
|
+ {label: 'tron', value: 'tron'},
|
|
|
+])
|
|
|
+
|
|
|
+const unitOptions = computed(() => [
|
|
|
+ {label: 'TRX', value: 'TRX'},
|
|
|
+ {label: 'USDT', value: 'USDT'},
|
|
|
+ {label: 'USDC', value: 'USDC'},
|
|
|
+])
|
|
|
+
|
|
|
function formatDash(v: unknown): string {
|
|
|
if (v == null || v === '') return '—'
|
|
|
return String(v)
|
|
|
@@ -86,7 +101,7 @@ function formatTimestamp(v: string | number | undefined): string {
|
|
|
|
|
|
/** 各列 width 之和,供 scroll-x 使用,保证超出视口时可横向滚动看全列 */
|
|
|
const VAULT_TX_COL_WIDTHS = [
|
|
|
- 120, 186, 200, 160,/* 120,*/ 96, 140, 200, 160, /*120,*/ 96, 140, 120, 112, 128, 96, 260,
|
|
|
+ 120, 200, 160,/* 120,*/ 96, 140, 200, 160, /*120,*/ 96, 140, 112, 128, 96, 120, 186, 260,
|
|
|
] as const
|
|
|
|
|
|
const tableScrollX = VAULT_TX_COL_WIDTHS.reduce((a, w) => a + w, 0) + 120
|
|
|
@@ -94,23 +109,14 @@ const tableScrollX = VAULT_TX_COL_WIDTHS.reduce((a, w) => a + w, 0) + 120
|
|
|
/** 表头与单元格均居中(titleAlign / align: center) */
|
|
|
const columns = computed<DataTableColumns<VaultTransactionItem>>(() => [
|
|
|
{
|
|
|
- title: () => t('vaultTx.colStatus'),
|
|
|
- key: 'status',
|
|
|
+ title: () => t('vaultTx.colBlockchain'),
|
|
|
+ key: 'blockchain',
|
|
|
width: 120,
|
|
|
titleAlign: 'center',
|
|
|
align: 'center',
|
|
|
- ellipsis: { tooltip: true },
|
|
|
+ ellipsis: {tooltip: true},
|
|
|
render: (row) =>
|
|
|
- h('span', { class: 'vault-tx__cell-text vault-tx__cell-status' }, formatDash(row.status)),
|
|
|
- },
|
|
|
- {
|
|
|
- title: () => t('vaultTx.colCreated'),
|
|
|
- key: 'createdTimestamp',
|
|
|
- width: 186,
|
|
|
- titleAlign: 'center',
|
|
|
- align: 'center',
|
|
|
- render: (row) =>
|
|
|
- h('span', { class: 'vault-tx__cell-text vault-tx__cell-mono' }, formatTimestamp(row.createdTimestamp)),
|
|
|
+ h('span', {class: 'vault-tx__cell-text'}, formatDash(row.blockchain)),
|
|
|
},
|
|
|
{
|
|
|
title: () => t('vaultTx.colSenderAddr'),
|
|
|
@@ -118,9 +124,9 @@ const columns = computed<DataTableColumns<VaultTransactionItem>>(() => [
|
|
|
width: 200,
|
|
|
titleAlign: 'center',
|
|
|
align: 'center',
|
|
|
- ellipsis: { tooltip: true },
|
|
|
+ ellipsis: {tooltip: true},
|
|
|
render: (row) =>
|
|
|
- h('span', { class: 'vault-tx__cell-text vault-tx__cell-mono' }, formatDash(row.senderAddress)),
|
|
|
+ h('span', {class: 'vault-tx__cell-text vault-tx__cell-mono'}, formatDash(row.senderAddress)),
|
|
|
},
|
|
|
{
|
|
|
title: () => t('vaultTx.colSenderLabel'),
|
|
|
@@ -128,8 +134,8 @@ const columns = computed<DataTableColumns<VaultTransactionItem>>(() => [
|
|
|
width: 160,
|
|
|
titleAlign: 'center',
|
|
|
align: 'center',
|
|
|
- ellipsis: { tooltip: true },
|
|
|
- render: (row) => h('span', { class: 'vault-tx__cell-text' }, formatDash(row.senderLabel)),
|
|
|
+ ellipsis: {tooltip: true},
|
|
|
+ render: (row) => h('span', {class: 'vault-tx__cell-text'}, formatDash(row.senderLabel)),
|
|
|
},
|
|
|
// {
|
|
|
// title: () => t('vaultTx.colSenderInternal'),
|
|
|
@@ -146,9 +152,9 @@ const columns = computed<DataTableColumns<VaultTransactionItem>>(() => [
|
|
|
width: 96,
|
|
|
titleAlign: 'center',
|
|
|
align: 'center',
|
|
|
- ellipsis: { tooltip: true },
|
|
|
+ ellipsis: {tooltip: true},
|
|
|
render: (row) =>
|
|
|
- h('span', { class: 'vault-tx__cell-text vault-tx__cell-unit' }, formatDash(row.senderAmountUnit)),
|
|
|
+ h('span', {class: 'vault-tx__cell-text vault-tx__cell-unit'}, formatDash(row.senderAmountUnit)),
|
|
|
},
|
|
|
{
|
|
|
title: () => t('vaultTx.colSenderAmount'),
|
|
|
@@ -157,7 +163,7 @@ const columns = computed<DataTableColumns<VaultTransactionItem>>(() => [
|
|
|
titleAlign: 'center',
|
|
|
align: 'center',
|
|
|
render: (row) =>
|
|
|
- h('span', { class: 'vault-tx__cell-num' }, formatAmount(row.senderAmount)),
|
|
|
+ h('span', {class: 'vault-tx__cell-num'}, formatAmount(row.senderAmount)),
|
|
|
},
|
|
|
{
|
|
|
title: () => t('vaultTx.colRecipientAddr'),
|
|
|
@@ -165,9 +171,9 @@ const columns = computed<DataTableColumns<VaultTransactionItem>>(() => [
|
|
|
width: 200,
|
|
|
titleAlign: 'center',
|
|
|
align: 'center',
|
|
|
- ellipsis: { tooltip: true },
|
|
|
+ ellipsis: {tooltip: true},
|
|
|
render: (row) =>
|
|
|
- h('span', { class: 'vault-tx__cell-text vault-tx__cell-mono' }, formatDash(row.recipientAddress)),
|
|
|
+ h('span', {class: 'vault-tx__cell-text vault-tx__cell-mono'}, formatDash(row.recipientAddress)),
|
|
|
},
|
|
|
{
|
|
|
title: () => t('vaultTx.colRecipientLabel'),
|
|
|
@@ -175,8 +181,8 @@ const columns = computed<DataTableColumns<VaultTransactionItem>>(() => [
|
|
|
width: 160,
|
|
|
titleAlign: 'center',
|
|
|
align: 'center',
|
|
|
- ellipsis: { tooltip: true },
|
|
|
- render: (row) => h('span', { class: 'vault-tx__cell-text' }, formatDash(row.recipientLabel)),
|
|
|
+ ellipsis: {tooltip: true},
|
|
|
+ render: (row) => h('span', {class: 'vault-tx__cell-text'}, formatDash(row.recipientLabel)),
|
|
|
},
|
|
|
// {
|
|
|
// title: () => t('vaultTx.colRecipientInternal'),
|
|
|
@@ -193,9 +199,9 @@ const columns = computed<DataTableColumns<VaultTransactionItem>>(() => [
|
|
|
width: 96,
|
|
|
titleAlign: 'center',
|
|
|
align: 'center',
|
|
|
- ellipsis: { tooltip: true },
|
|
|
+ ellipsis: {tooltip: true},
|
|
|
render: (row) =>
|
|
|
- h('span', { class: 'vault-tx__cell-text vault-tx__cell-unit' }, formatDash(row.recipientAmountUnit)),
|
|
|
+ h('span', {class: 'vault-tx__cell-text vault-tx__cell-unit'}, formatDash(row.recipientAmountUnit)),
|
|
|
},
|
|
|
{
|
|
|
title: () => t('vaultTx.colRecipientAmount'),
|
|
|
@@ -204,17 +210,7 @@ const columns = computed<DataTableColumns<VaultTransactionItem>>(() => [
|
|
|
titleAlign: 'center',
|
|
|
align: 'center',
|
|
|
render: (row) =>
|
|
|
- h('span', { class: 'vault-tx__cell-num' }, formatAmount(row.recipientAmount)),
|
|
|
- },
|
|
|
- {
|
|
|
- title: () => t('vaultTx.colBlockchain'),
|
|
|
- key: 'blockchain',
|
|
|
- width: 120,
|
|
|
- titleAlign: 'center',
|
|
|
- align: 'center',
|
|
|
- ellipsis: { tooltip: true },
|
|
|
- render: (row) =>
|
|
|
- h('span', { class: 'vault-tx__cell-text' }, formatDash(row.blockchain)),
|
|
|
+ h('span', {class: 'vault-tx__cell-num'}, formatAmount(row.recipientAmount)),
|
|
|
},
|
|
|
// {
|
|
|
// title: () => t('vaultTx.colBlockHeight'),
|
|
|
@@ -232,7 +228,7 @@ const columns = computed<DataTableColumns<VaultTransactionItem>>(() => [
|
|
|
titleAlign: 'center',
|
|
|
align: 'center',
|
|
|
render: (row) =>
|
|
|
- h('span', { class: 'vault-tx__cell-num' }, formatAmount(row.feeAmount)),
|
|
|
+ h('span', {class: 'vault-tx__cell-num'}, formatAmount(row.feeAmount)),
|
|
|
},
|
|
|
{
|
|
|
title: () => t('vaultTx.colFeeUnit'),
|
|
|
@@ -240,9 +236,28 @@ const columns = computed<DataTableColumns<VaultTransactionItem>>(() => [
|
|
|
width: 96,
|
|
|
titleAlign: 'center',
|
|
|
align: 'center',
|
|
|
- ellipsis: { tooltip: true },
|
|
|
+ ellipsis: {tooltip: true},
|
|
|
+ render: (row) =>
|
|
|
+ h('span', {class: 'vault-tx__cell-text vault-tx__cell-unit'}, formatDash(row.feeAmountUnit)),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: () => t('vaultTx.colStatus'),
|
|
|
+ key: 'status',
|
|
|
+ width: 120,
|
|
|
+ titleAlign: 'center',
|
|
|
+ align: 'center',
|
|
|
+ ellipsis: {tooltip: true},
|
|
|
render: (row) =>
|
|
|
- h('span', { class: 'vault-tx__cell-text vault-tx__cell-unit' }, formatDash(row.feeAmountUnit)),
|
|
|
+ h('span', {class: 'vault-tx__cell-text vault-tx__cell-status'}, formatDash(row.status)),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: () => t('vaultTx.colCreated'),
|
|
|
+ key: 'createdTimestamp',
|
|
|
+ width: 186,
|
|
|
+ titleAlign: 'center',
|
|
|
+ align: 'center',
|
|
|
+ render: (row) =>
|
|
|
+ h('span', {class: 'vault-tx__cell-text vault-tx__cell-mono'}, formatTimestamp(row.createdTimestamp)),
|
|
|
},
|
|
|
{
|
|
|
title: () => t('vaultTx.colTxId'),
|
|
|
@@ -250,10 +265,10 @@ const columns = computed<DataTableColumns<VaultTransactionItem>>(() => [
|
|
|
width: 260,
|
|
|
titleAlign: 'center',
|
|
|
align: 'center',
|
|
|
- ellipsis: { tooltip: true },
|
|
|
+ ellipsis: {tooltip: true},
|
|
|
render: (row) => {
|
|
|
const txid = row.transactionId?.trim()
|
|
|
- if (!txid) return h('span', { class: 'vault-tx__cell-text vault-tx__cell-mono' }, '—')
|
|
|
+ if (!txid) return h('span', {class: 'vault-tx__cell-text vault-tx__cell-mono'}, '—')
|
|
|
const unit = row.blockchain?.trim()
|
|
|
const baseUrl = unit === 'ethereum' ? ETH_TX_BASE_URL : TRON_TX_BASE_URL
|
|
|
return h(
|
|
|
@@ -298,8 +313,8 @@ async function load(): Promise<void> {
|
|
|
recipientAddress: filters.recipientAddress,
|
|
|
startTime,
|
|
|
endTime,
|
|
|
- // senderIsVaultAddress: filters.senderIsVaultAddress,
|
|
|
- // recipientIsVaultAddress: filters.recipientIsVaultAddress,
|
|
|
+ blockchain: filters.blockchain,
|
|
|
+ unit: filters.unit,
|
|
|
page: {
|
|
|
current: pagination.page,
|
|
|
row: pagination.pageSize
|
|
|
@@ -331,7 +346,15 @@ watch(
|
|
|
)
|
|
|
|
|
|
watch(
|
|
|
- () => [filters.senderLabel, filters.recipientLabel, filters.senderAddress, filters.recipientAddress, filters.timeRange],
|
|
|
+ () => [
|
|
|
+ filters.senderLabel,
|
|
|
+ filters.recipientLabel,
|
|
|
+ filters.senderAddress,
|
|
|
+ filters.recipientAddress,
|
|
|
+ filters.timeRange,
|
|
|
+ filters.blockchain,
|
|
|
+ filters.unit,
|
|
|
+ ],
|
|
|
() => {
|
|
|
pagination.page = 1
|
|
|
void load()
|
|
|
@@ -376,8 +399,8 @@ async function onExport(): Promise<void> {
|
|
|
recipientAddress: filters.recipientAddress,
|
|
|
startTime,
|
|
|
endTime,
|
|
|
- // senderIsVaultAddress: filters.senderIsVaultAddress,
|
|
|
- // recipientIsVaultAddress: filters.recipientIsVaultAddress,
|
|
|
+ blockchain: filters.blockchain,
|
|
|
+ unit: filters.unit,
|
|
|
page: {
|
|
|
current: pagination.page,
|
|
|
row: pagination.pageSize,
|
|
|
@@ -403,8 +426,8 @@ function onResetFilters(): void {
|
|
|
filters.senderAddress = null
|
|
|
filters.recipientAddress = null
|
|
|
filters.timeRange = null
|
|
|
- // filters.senderIsVaultAddress = null
|
|
|
- // filters.recipientIsVaultAddress = null
|
|
|
+ filters.blockchain = null
|
|
|
+ filters.unit = null
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
@@ -423,14 +446,28 @@ function onResetFilters(): void {
|
|
|
</div>
|
|
|
</div> -->
|
|
|
</template>
|
|
|
-
|
|
|
+
|
|
|
<n-spin :show="loading" class="vault-panel__spin">
|
|
|
<div v-if="vault.currentVaultId == null" class="vault-panel__empty-wrap">
|
|
|
- <n-empty size="large" :description="t('vaultTx.selectVaultHint')" />
|
|
|
+ <n-empty size="large" :description="t('vaultTx.selectVaultHint')"/>
|
|
|
</div>
|
|
|
<div v-else class="vault-panel__body">
|
|
|
<div class="vault-panel__toolbar">
|
|
|
<div class="vault-panel__filters">
|
|
|
+ <n-select
|
|
|
+ v-model:value="filters.blockchain"
|
|
|
+ :options="blockchainOptions"
|
|
|
+ :placeholder="t('vaultTx.colBlockchain')"
|
|
|
+ clearable
|
|
|
+ style="width: 180px"
|
|
|
+ />
|
|
|
+ <n-select
|
|
|
+ v-model:value="filters.unit"
|
|
|
+ :options="unitOptions"
|
|
|
+ :placeholder="t('vaultTx.Unit')"
|
|
|
+ clearable
|
|
|
+ style="width: 180px"
|
|
|
+ />
|
|
|
<n-input
|
|
|
v-model:value="filters.senderLabel"
|
|
|
:placeholder="t('vaultTx.colSenderLabel')"
|
|
|
@@ -463,20 +500,6 @@ function onResetFilters(): void {
|
|
|
:end-placeholder="t('vaultTx.filterEndTime')"
|
|
|
style="width: 420px"
|
|
|
/>
|
|
|
-<!-- <n-select-->
|
|
|
-<!-- v-model:value="filters.senderIsVaultAddress"-->
|
|
|
-<!-- :options="boolFilterOptions"-->
|
|
|
-<!-- :placeholder="t('vaultTx.colSenderInternal')"-->
|
|
|
-<!-- clearable-->
|
|
|
-<!-- style="width: 200px"-->
|
|
|
-<!-- />-->
|
|
|
-<!-- <n-select-->
|
|
|
-<!-- v-model:value="filters.recipientIsVaultAddress"-->
|
|
|
-<!-- :options="boolFilterOptions"-->
|
|
|
-<!-- :placeholder="t('vaultTx.colRecipientInternal')"-->
|
|
|
-<!-- clearable-->
|
|
|
-<!-- style="width: 200px"-->
|
|
|
-<!-- />-->
|
|
|
<n-button tertiary @click="onResetFilters">{{ t('vaultTx.filterReset') }}</n-button>
|
|
|
</div>
|
|
|
<n-button class="vault-panel__export" type="primary" secondary :loading="exporting" @click="onExport">
|
|
|
@@ -500,7 +523,7 @@ function onResetFilters(): void {
|
|
|
/>
|
|
|
</div>
|
|
|
<!-- 仅占位:让白卡片铺满剩余高度,表格本身不纵向拉伸 -->
|
|
|
- <div class="vault-panel__tail-spacer" aria-hidden="true" />
|
|
|
+ <div class="vault-panel__tail-spacer" aria-hidden="true"/>
|
|
|
</div>
|
|
|
</n-spin>
|
|
|
</n-card>
|
|
|
@@ -647,7 +670,8 @@ function onResetFilters(): void {
|
|
|
gap: 10px;
|
|
|
min-width: 0;
|
|
|
}
|
|
|
-.vault-panel__export{
|
|
|
+
|
|
|
+.vault-panel__export {
|
|
|
align-self: flex-start;
|
|
|
}
|
|
|
|