| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789 |
- <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()
- const message = useMessage()
- const vault = useVaultStore()
- const loading = ref(false)
- const exporting = ref(false)
- const rows = ref<VaultTransactionItem[]>([])
- const pagination = reactive({
- page: 1,
- pageSize: 10,
- itemCount: 0,
- showSizePicker: true,
- pageSizes: [10, 20, 50],
- onUpdatePage: (p: number) => {
- pagination.page = p
- void load()
- },
- onUpdatePageSize: (size: number) => {
- pagination.pageSize = size
- pagination.page = 1
- void load()
- },
- })
- const ETH_TX_BASE_URL = 'https://etherscan.io/tx/'
- const TRON_TX_BASE_URL = 'https://tronscan.org/#/transaction/'
- const filters = reactive<{
- senderLabel: string | null
- recipientLabel: string | null
- senderAddress: string | null
- recipientAddress: string | null
- timeRange: [number, number] | null
- }>({
- senderLabel: null,
- recipientLabel: null,
- senderAddress: null,
- recipientAddress: null,
- timeRange: null,
- })
- function formatDash(v: unknown): string {
- if (v == null || v === '') return '—'
- return String(v)
- }
- function formatAmount(v: string | number | undefined): string {
- if (v == null || v === '') return '—'
- return String(v)
- }
- /** 兼容秒级/毫秒级时间戳与 ISO 字符串 输出yyyy-MM-dd HH:mm:ss 格式 */
- function formatTimestamp(v: string | number | undefined): string {
- if (v == null || v === '') return '—'
- const format = (d: Date) => {
- const pad = (n: number) => String(n).padStart(2, '0')
- return (
- `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}` +
- ` ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
- )
- }
- if (typeof v === 'string' && Number.isNaN(Number(v))) {
- const d = new Date(v)
- return Number.isNaN(d.getTime()) ? v : format(d)
- }
- const n = typeof v === 'number' ? v : Number(v)
- if (Number.isNaN(n)) return String(v)
- const ms = n < 1e12 ? n * 1000 : n
- const d = new Date(ms)
- return Number.isNaN(d.getTime()) ? String(v) : format(d)
- }
- // function boolText(v: boolean | undefined): string {
- // if (v === true) return t('vaultTx.boolYes')
- // if (v === false) return t('vaultTx.boolNo')
- // return '—'
- // }
- /** 各列 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,
- ] as const
- 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',
- width: 120,
- titleAlign: 'center',
- align: 'center',
- 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)),
- },
- {
- title: () => t('vaultTx.colSenderAddr'),
- key: 'senderAddress',
- width: 200,
- titleAlign: 'center',
- align: 'center',
- ellipsis: { tooltip: true },
- render: (row) =>
- h('span', { class: 'vault-tx__cell-text vault-tx__cell-mono' }, formatDash(row.senderAddress)),
- },
- {
- title: () => t('vaultTx.colSenderLabel'),
- key: 'senderLabel',
- width: 160,
- titleAlign: 'center',
- align: 'center',
- ellipsis: { tooltip: true },
- render: (row) => h('span', { class: 'vault-tx__cell-text' }, formatDash(row.senderLabel)),
- },
- // {
- // title: () => t('vaultTx.colSenderInternal'),
- // key: 'senderIsVaultAddress',
- // width: 120,
- // titleAlign: 'center',
- // align: 'center',
- // render: (row) =>
- // h('span', { class: 'vault-tx__cell-text' }, boolText(row.senderIsVaultAddress)),
- // },
- {
- title: () => t('vaultTx.colSenderUnit'),
- key: 'senderAmountUnit',
- width: 96,
- titleAlign: 'center',
- align: 'center',
- ellipsis: { tooltip: true },
- render: (row) =>
- h('span', { class: 'vault-tx__cell-text vault-tx__cell-unit' }, formatDash(row.senderAmountUnit)),
- },
- {
- title: () => t('vaultTx.colSenderAmount'),
- key: 'senderAmount',
- width: 140,
- titleAlign: 'center',
- align: 'center',
- render: (row) =>
- h('span', { class: 'vault-tx__cell-num' }, formatAmount(row.senderAmount)),
- },
- {
- title: () => t('vaultTx.colRecipientAddr'),
- key: 'recipientAddress',
- width: 200,
- titleAlign: 'center',
- align: 'center',
- ellipsis: { tooltip: true },
- render: (row) =>
- h('span', { class: 'vault-tx__cell-text vault-tx__cell-mono' }, formatDash(row.recipientAddress)),
- },
- {
- title: () => t('vaultTx.colRecipientLabel'),
- key: 'recipientLabel',
- width: 160,
- titleAlign: 'center',
- align: 'center',
- ellipsis: { tooltip: true },
- render: (row) => h('span', { class: 'vault-tx__cell-text' }, formatDash(row.recipientLabel)),
- },
- // {
- // title: () => t('vaultTx.colRecipientInternal'),
- // key: 'recipientIsVaultAddress',
- // width: 120,
- // titleAlign: 'center',
- // align: 'center',
- // render: (row) =>
- // h('span', { class: 'vault-tx__cell-text' }, boolText(row.recipientIsVaultAddress)),
- // },
- {
- title: () => t('vaultTx.colRecipientUnit'),
- key: 'recipientAmountUnit',
- width: 96,
- titleAlign: 'center',
- align: 'center',
- ellipsis: { tooltip: true },
- render: (row) =>
- h('span', { class: 'vault-tx__cell-text vault-tx__cell-unit' }, formatDash(row.recipientAmountUnit)),
- },
- {
- title: () => t('vaultTx.colRecipientAmount'),
- key: 'recipientAmount',
- width: 140,
- 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)),
- },
- // {
- // title: () => t('vaultTx.colBlockHeight'),
- // key: 'minedInBlockHeight',
- // width: 112,
- // titleAlign: 'center',
- // align: 'center',
- // render: (row) =>
- // h('span', { class: 'vault-tx__cell-num' }, formatDash(row.minedInBlockHeight)),
- // },
- {
- title: () => t('vaultTx.colFee'),
- key: 'feeAmount',
- width: 128,
- titleAlign: 'center',
- align: 'center',
- render: (row) =>
- h('span', { class: 'vault-tx__cell-num' }, formatAmount(row.feeAmount)),
- },
- {
- title: () => t('vaultTx.colFeeUnit'),
- key: 'feeAmountUnit',
- width: 96,
- titleAlign: 'center',
- align: 'center',
- ellipsis: { tooltip: true },
- render: (row) =>
- h('span', { class: 'vault-tx__cell-text vault-tx__cell-unit' }, formatDash(row.feeAmountUnit)),
- },
- {
- title: () => t('vaultTx.colTxId'),
- key: 'transactionId',
- width: 260,
- titleAlign: 'center',
- align: 'center',
- ellipsis: { tooltip: true },
- render: (row) => {
- const txid = row.transactionId?.trim()
- 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(
- 'a',
- {
- class: 'vault-tx__cell-text vault-tx__cell-mono vault-tx__cell-link',
- href: `${baseUrl}${encodeURIComponent(txid)}`,
- target: '_blank',
- rel: 'noopener noreferrer',
- },
- txid
- )
- },
- },
- ])
- async function load(): Promise<void> {
- if (vault.currentVaultId == null) {
- rows.value = []
- pagination.itemCount = 0
- return
- }
- loading.value = true
- try {
- let startTime: string | null = null
- let endTime: string | null = null
- if (filters.timeRange?.[0] != null) {
- const d = new Date(filters.timeRange[0])
- const pad = (n: number) => String(n).padStart(2, '0')
- startTime = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} 00:00:00`
- }
- if (filters.timeRange?.[1] != null) {
- const d = new Date(filters.timeRange[1])
- const pad = (n: number) => String(n).padStart(2, '0')
- endTime = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} 23:59:59`
- }
- const res = await fetchVaultTransactions({
- vaultId: vault.currentVaultId,
- senderLabel: filters.senderLabel,
- recipientLabel: filters.recipientLabel,
- senderAddress: filters.senderAddress,
- recipientAddress: filters.recipientAddress,
- startTime,
- endTime,
- // senderIsVaultAddress: filters.senderIsVaultAddress,
- // recipientIsVaultAddress: filters.recipientIsVaultAddress,
- page: {
- current: pagination.page,
- row: pagination.pageSize
- }
- // page: pagination.page,
- // pageSize: ,
- })
- if (res.code === ApiCode.StatusOK && Array.isArray(res.data)) {
- rows.value = res.data
- const total = res.page?.rowTotal
- pagination.itemCount =
- typeof total === 'number' && Number.isFinite(total) ? total : res.data.length
- } else {
- rows.value = []
- pagination.itemCount = 0
- message.error(res.msg || t('vaultTx.loadFail'))
- }
- } finally {
- loading.value = false
- }
- }
- watch(
- () => vault.currentVaultId,
- () => {
- pagination.page = 1
- void load()
- }
- )
- watch(
- () => [filters.senderLabel, filters.recipientLabel, filters.senderAddress, filters.recipientAddress, filters.timeRange],
- () => {
- pagination.page = 1
- void load()
- }
- )
- onMounted(() => {
- void load()
- })
- function triggerFileDownload(blob: Blob, filename: string): void {
- const url = URL.createObjectURL(blob)
- const a = document.createElement('a')
- a.href = url
- a.download = filename
- a.rel = 'noopener'
- a.click()
- URL.revokeObjectURL(url)
- }
- async function onExport(): Promise<void> {
- if (vault.currentVaultId == null) return
- exporting.value = true
- try {
- let startTime: string | null = null
- let endTime: string | null = null
- if (filters.timeRange?.[0] != null) {
- const d = new Date(filters.timeRange[0])
- const pad = (n: number) => String(n).padStart(2, '0')
- startTime = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} 00:00:00`
- }
- if (filters.timeRange?.[1] != null) {
- const d = new Date(filters.timeRange[1])
- const pad = (n: number) => String(n).padStart(2, '0')
- endTime = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} 23:59:59`
- }
- const res = await exportVaultTransactions({
- vaultId: vault.currentVaultId,
- senderLabel: filters.senderLabel,
- recipientLabel: filters.recipientLabel,
- senderAddress: filters.senderAddress,
- recipientAddress: filters.recipientAddress,
- startTime,
- endTime,
- // senderIsVaultAddress: filters.senderIsVaultAddress,
- // recipientIsVaultAddress: filters.recipientIsVaultAddress,
- page: {
- current: pagination.page,
- row: pagination.pageSize,
- },
- })
- if ('error' in res) {
- message.error(res.error || t('vaultTx.exportFail'))
- return
- }
- const name = res.filename?.trim() || `vault-transactions-${pagination.page}.xlsx`
- triggerFileDownload(res.blob, name)
- message.success(t('vaultTx.exportSuccess'))
- } catch {
- message.error(t('vaultTx.exportFail'))
- } finally {
- exporting.value = false
- }
- }
- function onResetFilters(): void {
- filters.senderLabel = null
- filters.recipientLabel = null
- filters.senderAddress = null
- filters.recipientAddress = null
- filters.timeRange = null
- // filters.senderIsVaultAddress = null
- // filters.recipientIsVaultAddress = null
- }
- </script>
- <template>
- <div class="vault-list">
- <n-card class="vault-panel" :segmented="{ content: true }" size="medium">
- <template #header>
- <!-- <div class="vault-panel__header">
- <div class="vault-panel__titles">
- <h2 class="vault-panel__title">{{ t('vaultTx.cardTitle') }}</h2>
- <p class="vault-panel__desc">{{ t('vaultTx.cardSubtitle') }}</p>
- </div>
- <div v-if="vault.currentVaultId != null" class="vault-panel__meta">
- <span class="vault-panel__meta-label">{{ t('vaultTx.rowCountLabel') }}</span>
- <span class="vault-panel__meta-value">{{ pagination.itemCount }}</span>
- </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')" />
- </div>
- <div v-else class="vault-panel__body">
- <div class="vault-panel__toolbar">
- <div class="vault-panel__filters">
- <n-input
- v-model:value="filters.senderLabel"
- :placeholder="t('vaultTx.colSenderLabel')"
- clearable
- style="width: 200px"
- />
- <n-input
- v-model:value="filters.senderAddress"
- :placeholder="t('vaultTx.colSenderAddr')"
- clearable
- style="width: 260px"
- />
- <n-input
- v-model:value="filters.recipientLabel"
- :placeholder="t('vaultTx.colRecipientLabel')"
- clearable
- style="width: 200px"
- />
- <n-input
- v-model:value="filters.recipientAddress"
- :placeholder="t('vaultTx.colRecipientAddr')"
- clearable
- style="width: 260px"
- />
- <n-date-picker
- v-model:value="filters.timeRange"
- type="daterange"
- clearable
- :start-placeholder="t('vaultTx.filterStartTime')"
- :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">
- {{ t('vaultTx.export') }}
- </n-button>
- </div>
- <div class="vault-panel__table-frame">
- <n-data-table
- class="vault-panel__table"
- :columns="columns"
- :data="rows"
- :pagination="pagination"
- :bordered="true"
- striped
- bottom-bordered
- :single-line="false"
- size="medium"
- :scroll-x="tableScrollX"
- :scrollbar-props="{ trigger: 'none' }"
- :empty-description="t('vaultTx.empty')"
- />
- </div>
- <!-- 仅占位:让白卡片铺满剩余高度,表格本身不纵向拉伸 -->
- <div class="vault-panel__tail-spacer" aria-hidden="true" />
- </div>
- </n-spin>
- </n-card>
- </div>
- </template>
- <style scoped>
- .vault-list {
- width: 100%;
- flex: 1;
- min-height: 0;
- display: flex;
- flex-direction: column;
- }
- .vault-panel {
- flex: 1;
- min-height: 0;
- max-width: 100%;
- display: flex;
- flex-direction: column;
- overflow: hidden;
- background: var(--vt-bg-elevated) !important;
- border: 1px solid var(--vt-divider) !important;
- box-shadow: var(--vt-shadow-card);
- --n-padding-top: 0;
- --n-padding-bottom: 0;
- --n-padding-left: 0;
- --n-padding-right: 0;
- }
- .vault-panel :deep(.n-card-header) {
- padding: 20px 22px 16px;
- border-bottom: 1px solid var(--vt-divider);
- }
- /* 卡片内容区铺满卡片剩余高度;内边距 15px */
- .vault-panel :deep(.n-card-content) {
- flex: 1;
- min-height: 0;
- display: flex;
- flex-direction: column;
- overflow-y: scroll;
- padding: 15px !important;
- box-sizing: border-box;
- }
- .vault-panel__header {
- display: flex;
- align-items: flex-start;
- justify-content: space-between;
- gap: 16px;
- }
- .vault-panel__titles {
- min-width: 0;
- }
- .vault-panel__title {
- margin: 0;
- font-size: 17px;
- font-weight: 600;
- letter-spacing: -0.02em;
- color: var(--vt-text);
- line-height: 1.3;
- }
- .vault-panel__desc {
- margin: 6px 0 0;
- font-size: 13px;
- line-height: 1.45;
- color: var(--vt-text-muted);
- }
- .vault-panel__meta {
- flex-shrink: 0;
- display: inline-flex;
- align-items: baseline;
- gap: 6px;
- padding: 6px 12px;
- border-radius: 999px;
- background: var(--vt-brand-soft);
- border: 1px solid rgba(79, 70, 229, 0.15);
- }
- .vault-panel__meta-label {
- font-size: 12px;
- font-weight: 500;
- color: var(--vt-text-muted);
- }
- .vault-panel__meta-value {
- font-size: 15px;
- font-weight: 700;
- font-variant-numeric: tabular-nums;
- color: var(--vt-brand);
- }
- .vault-panel__spin {
- flex: 1;
- min-height: 0;
- display: flex;
- flex-direction: column;
- }
- .vault-panel__spin :deep(.n-spin-content) {
- flex: 1;
- min-height: 0;
- display: flex;
- flex-direction: column;
- }
- .vault-panel__empty-wrap {
- flex: 1;
- min-height: 0;
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 24px 0;
- }
- .vault-panel__body {
- flex: 1;
- min-height: 0;
- display: flex;
- flex-direction: column;
- align-items: stretch;
- }
- .vault-panel__toolbar {
- flex-shrink: 0;
- display: flex;
- justify-content: space-between;
- align-items: center;
- gap: 10px;
- padding: 0 14px 10px;
- box-sizing: border-box;
- }
- .vault-panel__filters {
- display: flex;
- flex-wrap: wrap;
- align-items: center;
- gap: 10px;
- min-width: 0;
- }
- .vault-panel__export{
- align-self: flex-start;
- }
- .vault-panel__table-frame {
- flex: 0 0 auto;
- width: 100%;
- min-width: 0;
- padding: 12px 14px 10px;
- box-sizing: border-box;
- /* border: 1px solid var(--vt-border); */
- /* border-radius: 12px; */
- /* background: #fafbfc; */
- overflow-x: auto;
- overflow-y: visible;
- }
- .vault-panel__tail-spacer {
- flex: 1 1 auto;
- min-height: 0;
- min-width: 0;
- }
- .vault-panel__table {
- width: 100%;
- max-width: 100%;
- min-width: 0;
- }
- /* 表格:表头、分隔、对齐与数字字体 */
- .vault-panel__table :deep(.n-data-table) {
- --n-th-padding: 11px 14px;
- --n-td-padding: 11px 14px;
- }
- .vault-panel__table :deep(.n-data-table-wrapper) {
- min-width: 0;
- border-radius: 10px;
- overflow: hidden;
- border: 1px solid #e5e7eb;
- background: #fff;
- box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
- }
- .vault-panel__table :deep(.n-data-table-base-table-header) {
- border-radius: 10px 10px 0 0;
- }
- .vault-panel__table :deep(.n-data-table-th) {
- text-align: center !important;
- font-weight: 600;
- font-size: 12px;
- line-height: 1.35;
- letter-spacing: 0.01em;
- color: #475569 !important;
- background: #f1f5f9 !important;
- border-color: #e2e8f0 !important;
- border-bottom: 1px solid #e2e8f0 !important;
- }
- .vault-panel__table :deep(.n-data-table-th__title-wrapper) {
- justify-content: center;
- }
- .vault-panel__table :deep(.n-data-table-td) {
- text-align: center !important;
- font-size: 13px;
- line-height: 1.45;
- color: var(--vt-text);
- border-color: #eef2f7 !important;
- vertical-align: middle;
- }
- .vault-panel__table :deep(.n-data-table-tr:not(.n-data-table-tr--summary):hover .n-data-table-td) {
- background: #f8fafc !important;
- }
- .vault-panel__table :deep(.n-data-table__pagination) {
- padding: 12px 4px 4px;
- margin-top: 2px;
- border-top: 1px solid #eef2f7;
- justify-content: flex-end;
- }
- .vault-panel__table :deep(.n-data-table-empty) {
- padding: 40px 16px 48px;
- background: #fff;
- }
- .vault-panel__table :deep(.n-data-table-empty .n-empty__description) {
- margin-top: 12px;
- font-size: 14px;
- color: var(--vt-text-muted);
- }
- /* 单元格内层:与表头一致居中 */
- .vault-panel__table :deep(.vault-tx__cell-text),
- .vault-panel__table :deep(.vault-tx__cell-num) {
- display: inline-block;
- max-width: 100%;
- vertical-align: middle;
- text-align: center;
- }
- .vault-panel__table :deep(.vault-tx__cell-mono) {
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
- font-size: 12.5px;
- letter-spacing: -0.01em;
- }
- .vault-panel__table :deep(.vault-tx__cell-num) {
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
- font-size: 13px;
- font-variant-numeric: tabular-nums;
- font-feature-settings: 'tnum' 1;
- letter-spacing: -0.02em;
- }
- .vault-panel__table :deep(.vault-tx__cell-unit) {
- font-weight: 600;
- font-size: 12px;
- color: #64748b;
- text-transform: uppercase;
- }
- .vault-panel__table :deep(.vault-tx__cell-link) {
- color: var(--vt-brand);
- text-decoration: none;
- }
- .vault-panel__table :deep(.vault-tx__cell-link:hover) {
- text-decoration: underline;
- }
- .vault-panel__table :deep(.vault-tx__cell-status) {
- font-weight: 500;
- font-size: 12.5px;
- color: #0f172a;
- }
- </style>
|