fix(player): 优化桌面快速下注 hover 并修复充值 API 重复方法

删除 deposit.service 中重复的 getPlayerDepositOrder,避免 API 编译失败引发 500;快速下注弹层按卡片实例激活,同场赛事不再多处联动,移入快速下注区域时保持 VS 动画;记录列表改为整行可点,编号统一中性色样式。
This commit is contained in:
2026-07-02 11:12:09 +08:00
parent 66ac69c7a7
commit 8000c23418
12 changed files with 122 additions and 102 deletions

View File

@@ -601,47 +601,6 @@ export class DepositService {
});
}
async getPlayerDepositOrder(playerId: bigint, orderId: bigint) {
const order = await this.prisma.depositOrder.findFirst({
where: { id: orderId, playerId },
include: {
paymentMethod: {
select: { bankName: true, usdtAddress: true, displayName: true, methodType: true },
},
},
});
if (!order) throw appBadRequest('ORDER_NOT_FOUND');
const auditMap = await this.attachPlayerAuditLogs([order]);
const o = order;
return {
id: o.id.toString(),
orderNo: o.orderNo,
paymentMethodId: o.paymentMethodId.toString(),
methodType: o.methodType,
amount: o.amount.toString(),
screenshotUrl: o.screenshotUrl,
status: o.status,
approvedAmount: o.approvedAmount?.toString() ?? null,
rejectReason: o.rejectReason,
remark: o.remark,
createdAt: o.createdAt,
reviewedAt: o.reviewedAt,
paymentMethodName: o.paymentMethod?.displayName ?? o.paymentMethod?.bankName ?? o.paymentMethod?.usdtAddress ?? null,
auditLogs: (auditMap.get(o.id.toString()) ?? []).map((log) => ({
id: log.id,
action: log.action,
actorType: log.actorType,
statusBefore: log.statusBefore,
statusAfter: log.statusAfter,
amount: log.amount,
approvedAmount: log.approvedAmount,
remark: log.remark,
createdAt: log.createdAt,
})),
};
}
async getPlayerDepositOrders(playerId: bigint, page = 1, pageSize = 20) {
const skip = (page - 1) * pageSize;
const where = { playerId };

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref, computed } from 'vue';
import { ref, computed, getCurrentInstance } from 'vue';
import { useRouter } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { teamFlagUrl } from '../utils/teamFlag';
@@ -82,10 +82,15 @@ const liveScoreText = computed(() => {
const router = useRouter();
const slip = useBetSlipStore();
const auth = useAuthStore();
const { openAt, visible: popoverVisible, pendingItem, cancelClose, scheduleClose } = useDesktopBetPopover();
const { openAt, visible: popoverVisible, pendingItem, cancelClose, scheduleClose, isActiveForCard } = useDesktopBetPopover();
const cardRootId = `bet-card-${props.match.id}-${getCurrentInstance()?.uid ?? 0}`;
const isCardEngaged = computed(() => isActiveForCard(cardRootId));
function getHoveredSide() {
if (!popoverVisible.value || !pendingItem.value) return '';
if (!isActiveForCard(cardRootId)) return '';
if (String(pendingItem.value.matchId) !== String(props.match.id)) return '';
const selId = pendingItem.value.selectionId;
@@ -199,8 +204,15 @@ function goMatchDetail() {
<template>
<article
class="match-card"
:class="{ 'match-card--phase': phase !== 'open', 'no-quick-bet': noQuickBet }"
:data-bet-card-root="cardRootId"
:class="{
'match-card--phase': phase !== 'open',
'no-quick-bet': noQuickBet,
'match-card--engaged': isCardEngaged,
}"
@click="emit('bet', match.id)"
@mouseenter="cancelClose"
@mouseleave="scheduleClose()"
>
<span v-if="phase === 'open'" class="status-tag status-tag--open">{{ t('bet.status_open') }}</span>
<span v-else-if="phase === 'settled'" class="status-tag status-tag--settled">{{ phaseLabel }}</span>
@@ -250,7 +262,7 @@ function goMatchDetail() {
</button>
<!-- Morphing Quick Bet panel (Desktop Only, disabled when noQuickBet=true) -->
<div v-if="!noQuickBet" class="card-quick-bet" @click.stop @mouseenter="cancelClose" @mouseleave="scheduleClose()">
<div v-if="!noQuickBet" class="card-quick-bet" @click.stop>
<div class="quick-bet-tabs" v-if="getAvailableMarketsForMatch(match).length">
<button
v-for="m in getAvailableMarketsForMatch(match)"
@@ -486,36 +498,36 @@ function goMatchDetail() {
}
@media (hover: hover) {
.match-card:not(.no-quick-bet):hover {
.match-card:not(.no-quick-bet):is(:hover, .match-card--engaged) {
border-color: var(--border-gold);
box-shadow: var(--shadow-gold);
}
/* 整行保持原位,间距自然 */
.match-card:not(.no-quick-bet):hover .teams-row {
.match-card:not(.no-quick-bet):is(:hover, .match-card--engaged) .teams-row {
transform: translateY(0);
padding: 0 40px;
}
/* .team 取消自身 translateY */
.match-card:not(.no-quick-bet):hover .team {
.match-card:not(.no-quick-bet):is(:hover, .match-card--engaged) .team {
transform: translateY(0);
gap: 3px;
}
/* 旗帜缩小到 40×28 */
.match-card:not(.no-quick-bet):hover .team-flag {
.match-card:not(.no-quick-bet):is(:hover, .match-card--engaged) .team-flag {
width: 40px;
height: 28px;
}
.match-card:not(.no-quick-bet):hover .team-flag.flag-logo {
.match-card:not(.no-quick-bet):is(:hover, .match-card--engaged) .team-flag.flag-logo {
width: 28px;
height: 28px;
}
/* 队名缩小并禁止换行 */
.match-card:not(.no-quick-bet):hover .team-name {
.match-card:not(.no-quick-bet):is(:hover, .match-card--engaged) .team-name {
font-size: 10px;
white-space: nowrap;
overflow: hidden;
@@ -524,7 +536,7 @@ function goMatchDetail() {
}
/* 隐藏开赛时间 */
.match-card:not(.no-quick-bet):hover .kickoff {
.match-card:not(.no-quick-bet):is(:hover, .match-card--engaged) .kickoff {
opacity: 0;
height: 0;
margin: 0;
@@ -533,19 +545,19 @@ function goMatchDetail() {
}
/* VS / 比分 */
.match-card:not(.no-quick-bet):hover .vs,
.match-card:not(.no-quick-bet):hover .live-score {
.match-card:not(.no-quick-bet):is(:hover, .match-card--engaged) .vs,
.match-card:not(.no-quick-bet):is(:hover, .match-card--engaged) .live-score {
font-size: 16px;
}
/* 下注按钮淡出(保留布局空间避免高度抖动) */
.match-card:not(.no-quick-bet):hover .bet-btn {
.match-card:not(.no-quick-bet):is(:hover, .match-card--engaged) .bet-btn {
opacity: 0;
pointer-events: none;
}
/* 快速下注面板淡入 */
.match-card:not(.no-quick-bet):hover .card-quick-bet {
.match-card:not(.no-quick-bet):is(:hover, .match-card--engaged) .card-quick-bet {
opacity: 1;
pointer-events: auto;
transform: translateY(0);

View File

@@ -26,7 +26,7 @@ const emit = defineEmits<{
}>();
const { t } = useI18n();
const { scheduleClose, cancelClose } = useDesktopBetPopover();
const { cancelClose } = useDesktopBetPopover();
const columns = computed(() =>
groupCorrectScoreSelections(
@@ -51,14 +51,18 @@ function formatOdds(odds: string) {
</script>
<template>
<div class="cs-panel" :class="{ 'cs-panel--locked': locked, 'cs-panel--dense': dense }">
<div
class="cs-panel"
:class="{ 'cs-panel--locked': locked, 'cs-panel--dense': dense }"
@mouseenter="cancelClose"
>
<div class="cols-head">
<span>{{ t('bet.col_home') }}</span>
<span>{{ t('bet.col_draw') }}</span>
<span>{{ t('bet.col_away') }}</span>
</div>
<div class="cols-grid" @mouseenter="cancelClose" @mouseleave="scheduleClose()">
<div class="cols-grid">
<div v-for="colKey in ['home', 'draw', 'away'] as const" :key="colKey" class="col">
<button
v-for="sel in columns[colKey]"

View File

@@ -25,7 +25,7 @@ const props = defineProps<{
const emit = defineEmits<{ pick: [id: string, event?: MouseEvent] }>();
const { t } = useI18n();
const { scheduleClose, cancelClose } = useDesktopBetPopover();
const { cancelClose } = useDesktopBetPopover();
function label(sel: (typeof props.selections)[number]) {
if (sel.selectionDisplayName?.trim()) return sel.selectionDisplayName;
@@ -56,7 +56,7 @@ const panelStyle = computed(() =>
</script>
<template>
<div class="wrap" :class="{ compact, horizontal, desktopCard, locked }" @mouseenter="cancelClose" @mouseleave="scheduleClose()">
<div class="wrap" :class="{ compact, horizontal, desktopCard, locked }" @mouseenter="cancelClose">
<div
class="panel"
:class="{ horizontal, 'desktop-card': desktopCard }"

View File

@@ -5,6 +5,7 @@ const visible = ref(false);
const anchorX = ref(0);
const anchorY = ref(0);
const pendingItem = ref<SlipItem | null>(null);
const activeCardRootId = ref<string | null>(null);
const placement = ref<'top' | 'bottom'>('bottom');
let closeTimer: number | undefined = undefined;
@@ -45,12 +46,15 @@ export function useDesktopBetPopover() {
anchorX.value = x;
anchorY.value = y;
pendingItem.value = item;
const root = el?.closest?.('[data-bet-card-root]') as HTMLElement | null;
activeCardRootId.value = root?.dataset.betCardRoot ?? null;
visible.value = true;
}
function close() {
visible.value = false;
pendingItem.value = null;
activeCardRootId.value = null;
if (closeTimer !== undefined) {
window.clearTimeout(closeTimer);
closeTimer = undefined;
@@ -64,6 +68,7 @@ export function useDesktopBetPopover() {
closeTimer = window.setTimeout(() => {
visible.value = false;
pendingItem.value = null;
activeCardRootId.value = null;
closeTimer = undefined;
}, delay);
}
@@ -75,15 +80,22 @@ export function useDesktopBetPopover() {
}
}
function isActiveForCard(cardRootId: string | null | undefined) {
if (!cardRootId || !visible.value || !pendingItem.value) return false;
return activeCardRootId.value === cardRootId;
}
return {
visible,
anchorX,
anchorY,
pendingItem,
activeCardRootId,
placement,
openAt,
close,
scheduleClose,
cancelClose,
isActiveForCard,
};
}

View File

@@ -208,24 +208,23 @@
transition: background 0.15s;
}
.desktop-records-table tbody tr.hover-row:hover {
.desktop-records-table tbody tr.clickable-row {
cursor: pointer;
}
.desktop-records-table tbody tr.hover-row:hover,
.desktop-records-table tbody tr.clickable-row:hover {
background: rgba(255, 255, 255, 0.04);
}
.desktop-records-table .link-cell {
.desktop-records-table .id-cell {
color: var(--text);
font-weight: 700;
text-decoration: none;
font-family: 'SF Mono', 'Consolas', monospace;
font-size: 12px;
letter-spacing: 0.03em;
}
.desktop-records-table .link-cell:hover {
color: #fff;
text-decoration: underline;
}
.desktop-records-table .num-cell {
text-align: right;
font-variant-numeric: tabular-nums;

View File

@@ -22,7 +22,7 @@ const { banners, hotMatches, upcomingMatches, loading, load, announcementItems }
const slip = useBetSlipStore();
const auth = useAuthStore();
const { openAt, visible: popoverVisible, pendingItem, cancelClose, scheduleClose } = useDesktopBetPopover();
const { openAt, visible: popoverVisible, pendingItem, cancelClose, scheduleClose, isActiveForCard } = useDesktopBetPopover();
const activeMarketTypes = ref<Record<string, string>>({});
@@ -141,8 +141,9 @@ function getSelLabel(sel: any, marketType: string, lineValue?: string | number |
return resolveSelectionLabel(t, sel.selectionCode || '', sel.selectionName || '', { lineValue });
}
function getHoveredSideForMatch(match: PlayerHomeMatch | null) {
function getHoveredSideForMatch(match: PlayerHomeMatch | null, cardRootId: string) {
if (!match || !popoverVisible.value || !pendingItem.value) return '';
if (!isActiveForCard(cardRootId)) return '';
if (String(pendingItem.value.matchId) !== String(match.id)) return '';
const selId = pendingItem.value.selectionId;
@@ -203,7 +204,15 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null) {
<template v-else-if="featuredMatch">
<!-- 焦点大卡 -->
<div class="featured-match anim-fade-up" style="--anim-delay:240ms" @click.self="goMatch(featuredMatch.id)">
<div
class="featured-match anim-fade-up"
:class="{ 'featured-match--engaged': isActiveForCard(`featured-${featuredMatch.id}`) }"
:data-bet-card-root="`featured-${featuredMatch.id}`"
style="--anim-delay:240ms"
@click.self="goMatch(featuredMatch.id)"
@mouseenter="cancelClose"
@mouseleave="scheduleClose()"
>
<div class="featured-top" @click="goMatch(featuredMatch.id)">
<div class="featured-meta">
<span class="league-tag lg">{{ featuredMatch.leagueName }}</span>
@@ -215,7 +224,7 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null) {
<span class="featured-time">{{ formatKickoff(featuredMatch.startTime) }}</span>
</div>
<div class="featured-teams" :class="getHoveredSideForMatch(featuredMatch)" @click="goMatch(featuredMatch.id)">
<div class="featured-teams" :class="getHoveredSideForMatch(featuredMatch, `featured-${featuredMatch.id}`)" @click="goMatch(featuredMatch.id)">
<div class="featured-team">
<TeamEmblem
size="lg"
@@ -266,7 +275,11 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null) {
v-for="(match, idx) in restHotMatches"
:key="match.id"
class="match-card anim-fade-up"
:class="{ 'match-card--engaged': isActiveForCard(`hot-${match.id}`) }"
:data-bet-card-root="`hot-${match.id}`"
:style="{ '--anim-delay': (320 + idx * 60) + 'ms' }"
@mouseenter="cancelClose"
@mouseleave="scheduleClose()"
>
<div class="match-info-side" @click="goMatch(match.id)">
<!-- Default info layout (visible at rest) -->
@@ -302,7 +315,7 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null) {
</div>
<!-- Hover versus layout (visible on hover) -->
<div class="hover-versus-layout" :class="getHoveredSideForMatch(match)">
<div class="hover-versus-layout" :class="getHoveredSideForMatch(match, `hot-${match.id}`)">
<div class="hover-team home-slide">
<TeamEmblem
size="md"
@@ -375,7 +388,11 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null) {
v-for="(match, idx) in upcomingList"
:key="match.id"
class="match-card anim-fade-up"
:class="{ 'match-card--engaged': isActiveForCard(`upcoming-${match.id}`) }"
:data-bet-card-root="`upcoming-${match.id}`"
:style="{ '--anim-delay': (260 + idx * 50) + 'ms' }"
@mouseenter="cancelClose"
@mouseleave="scheduleClose()"
>
<div class="match-info-side" @click="goMatch(match.id)">
<!-- Default info layout (visible at rest) -->
@@ -410,7 +427,7 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null) {
</div>
<!-- Hover versus layout (visible on hover) -->
<div class="hover-versus-layout" :class="getHoveredSideForMatch(match)">
<div class="hover-versus-layout" :class="getHoveredSideForMatch(match, `upcoming-${match.id}`)">
<div class="hover-team home-slide">
<TeamEmblem
size="md"
@@ -483,8 +500,12 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null) {
v-for="(m, idx) in sideRecommendMatches"
:key="m.id"
class="side-recommend-item anim-fade-up"
:class="{ 'side-recommend-item--engaged': isActiveForCard(`sidebar-${m.id}`) }"
:data-bet-card-root="`sidebar-${m.id}`"
:style="{ '--anim-delay': (200 + idx * 70) + 'ms' }"
@click="goMatch(m.id)"
@mouseenter="cancelClose"
@mouseleave="scheduleClose()"
>
<div class="sri-top-row">
<span class="sri-league">{{ m.leagueName }}</span>
@@ -502,7 +523,7 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null) {
<span class="sri-preview-league">{{ m.leagueName }}</span>
<span class="sri-preview-time">{{ formatKickoff(m.startTime) }}</span>
</div>
<div class="sri-preview-vs" :class="getHoveredSideForMatch(m)">
<div class="sri-preview-vs" :class="getHoveredSideForMatch(m, `sidebar-${m.id}`)">
<div class="sri-preview-team home-team">
<TeamEmblem size="md" :team-code="m.homeTeamCode" :team-name="m.homeTeamName" :logo-url="m.homeTeamLogoUrl" />
<span>{{ m.homeTeamName }}</span>
@@ -814,7 +835,7 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null) {
min-height: 76px;
}
.match-card:hover {
.match-card:is(:hover, .match-card--engaged) {
border-color: var(--border-gold);
box-shadow: var(--shadow-gold);
transform: translateY(-1px);
@@ -840,7 +861,7 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null) {
z-index: 1;
}
.match-card:hover .match-info-side {
.match-card:is(:hover, .match-card--engaged) .match-info-side {
background: rgba(255, 255, 255, 0.02);
}
@@ -1186,7 +1207,7 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null) {
transition: opacity 0.35s cubic-bezier(0.25, 0.8, 0.25, 1), transform 0.35s cubic-bezier(0.25, 0.8, 0.25, 1);
}
.match-card:hover .default-info-layout {
.match-card:is(:hover, .match-card--engaged) .default-info-layout {
opacity: 0;
transform: translateY(-8px) scale(0.95);
pointer-events: none;
@@ -1211,7 +1232,7 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null) {
border-radius: 8px 0 0 8px;
}
.match-card:hover .hover-versus-layout {
.match-card:is(:hover, .match-card--engaged) .hover-versus-layout {
opacity: 1;
transform: translateY(0) scale(1);
pointer-events: auto;
@@ -1229,7 +1250,7 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null) {
flex: 1;
}
.match-card:hover .hover-team.home-slide {
.match-card:is(:hover, .match-card--engaged) .hover-team.home-slide {
transform: translateX(0);
opacity: 1;
}
@@ -1246,7 +1267,7 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null) {
flex: 1;
}
.match-card:hover .hover-team.away-slide {
.match-card:is(:hover, .match-card--engaged) .hover-team.away-slide {
transform: translateX(0);
opacity: 1;
}
@@ -1276,7 +1297,7 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null) {
flex-shrink: 0;
}
.match-card:hover .hover-vs-glow {
.match-card:is(:hover, .match-card--engaged) .hover-vs-glow {
transform: scale(1);
opacity: 1;
animation: vs-clash-impact 0.3s ease-out 0.35s;
@@ -1347,7 +1368,7 @@ function getHoveredSideForMatch(match: PlayerHomeMatch | null) {
gap: 10px;
}
.side-recommend-item:hover .sri-preview-card {
.side-recommend-item:is(:hover, .side-recommend-item--engaged) .sri-preview-card {
opacity: 1;
transform: translateY(-50%) translateX(0);
pointer-events: auto;

View File

@@ -23,7 +23,7 @@ const router = useRouter();
const { t, locale } = useI18n();
const slip = useBetSlipStore();
const auth = useAuthStore();
const { openAt, visible: popoverVisible, pendingItem: popoverItem } = useDesktopBetPopover();
const { openAt, visible: popoverVisible, pendingItem: popoverItem, cancelClose, scheduleClose } = useDesktopBetPopover();
const { pendingLocate, clearLocate } = useDesktopBetLocate();
function goBack() {
@@ -349,7 +349,12 @@ function getHoveredSide() {
<template v-else-if="match">
<!-- High Density Score Band -->
<div class="match-score-band" :class="[{ 'phase-settled': matchPhase === 'settled' }, getHoveredSide()]">
<div
class="match-score-band"
:class="[{ 'phase-settled': matchPhase === 'settled' }, getHoveredSide()]"
@mouseenter="cancelClose"
@mouseleave="scheduleClose()"
>
<div class="team-side home">
<TeamEmblem size="xl" :team-code="match.homeTeamCode" :team-name="match.homeTeamName" :logo-url="match.homeTeamLogoUrl" />
<span class="name">{{ match.homeTeamName }}</span>
@@ -413,6 +418,8 @@ function getHoveredSide() {
:key="market.id"
class="market-card"
:class="{ locked: isMarketLocked(market) }"
@mouseenter="cancelClose"
@mouseleave="scheduleClose()"
>
<div class="market-hdr">
<span class="market-title">{{ marketLabel(market) }}</span>
@@ -441,6 +448,8 @@ function getHoveredSide() {
:key="market.id"
class="score-block"
:class="{ locked: isMarketLocked(market) }"
@mouseenter="cancelClose"
@mouseleave="scheduleClose()"
>
<div class="score-block-hdr">
<span>{{ marketLabel(market) }}</span>

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import { ref, onMounted, onActivated } from 'vue';
import { useI18n } from 'vue-i18n';
import { RouterLink } from 'vue-router';
import { useRouter } from 'vue-router';
import api from '../../api';
import GoldSpinner from '../../components/GoldSpinner.vue';
import Pagination from '../../components/desktop/Pagination.vue';
@@ -11,6 +11,7 @@ import { useOnLocaleChange } from '../../composables/useOnLocaleChange';
const COL_COUNT = 8;
const { t } = useI18n();
const router = useRouter();
const items = ref<BetHistoryItem[]>([]);
const total = ref(0);
@@ -149,10 +150,13 @@ function statusLabel(status: string) {
</td>
</tr>
<template v-else-if="items.length">
<tr v-for="bet in items" :key="bet.betNo" class="hover-row">
<td>
<RouterLink :to="`/bets/${bet.betNo}`" class="link-cell">{{ bet.betNo }}</RouterLink>
</td>
<tr
v-for="bet in items"
:key="bet.betNo"
class="hover-row clickable-row"
@click="router.push(`/bets/${bet.betNo}`)"
>
<td class="id-cell">{{ bet.betNo }}</td>
<td>{{ bet.matchTitle || '-' }}</td>
<td class="muted-cell">{{ bet.pickLabel || '-' }}</td>
<td class="num-cell">{{ bet.totalOdds ?? '-' }}</td>

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import { ref, onMounted, onActivated } from 'vue';
import { useI18n } from 'vue-i18n';
import { RouterLink } from 'vue-router';
import { RouterLink, useRouter } from 'vue-router';
import api from '../../api';
import GoldSpinner from '../../components/GoldSpinner.vue';
import Pagination from '../../components/desktop/Pagination.vue';
@@ -11,6 +11,7 @@ import { formatMoney } from '../../utils/localeDisplay';
const COL_COUNT = 5;
const { t, locale } = useI18n();
const router = useRouter();
type RechargeOrder = {
id: string;
@@ -104,12 +105,13 @@ function statusLabel(status: string) {
</td>
</tr>
<template v-else-if="items.length">
<tr v-for="order in items" :key="order.id" class="hover-row">
<td>
<RouterLink :to="`/wallet/recharge/history/${order.id}`" class="link-cell">
{{ order.orderNo || order.id }}
</RouterLink>
</td>
<tr
v-for="order in items"
:key="order.id"
class="hover-row clickable-row"
@click="router.push(`/wallet/recharge/history/${order.id}`)"
>
<td class="id-cell">{{ order.orderNo || order.id }}</td>
<td>{{ methodLabel(order) }}</td>
<td class="num-cell">{{ formatMoney(order.amount, locale) }}</td>
<td>

View File

@@ -93,8 +93,7 @@ onActivated(() => loadPage(1));
<tr
v-for="tx in items"
:key="tx.transactionId"
class="hover-row"
style="cursor:pointer"
class="hover-row clickable-row"
@click="router.push(`/wallet/transactions/${tx.transactionId}`)"
>
<td class="type-cell">{{ txLabel(tx) }}</td>

View File

@@ -112,8 +112,7 @@ onActivated(() => fetchData(1));
<tr
v-for="tx in items"
:key="tx.transactionId"
class="hover-row"
style="cursor: pointer"
class="hover-row clickable-row"
@click="router.push(`/wallet/transactions/${tx.transactionId}`)"
>
<td class="type-cell">{{ txLabel(tx) }}</td>