fix(player): apply heading/data font tokens globally across all desktop components

This commit is contained in:
mars
2026-07-13 09:55:26 +08:00
parent 3af2fe72d4
commit 5a6a8195f8
11 changed files with 138 additions and 56 deletions

View File

@@ -85,12 +85,12 @@ const SEL_TRANS: Record<string, Record<string, string>> = {
'主胜': { 'en-US': 'Home Win', 'ms-MY': 'Rumah Menang' },
'客胜': { 'en-US': 'Away Win', 'ms-MY': 'Tandang Menang' },
'和局': { 'en-US': 'Draw', 'ms-MY': 'Seri' },
'主': { 'en-US': 'Home', 'ms-MY': 'Rumah' },
'客': { 'en-US': 'Away', 'ms-MY': 'Tandang' },
'大': { 'en-US': 'Over', 'ms-MY': 'Atas' },
'小': { 'en-US': 'Under', 'ms-MY': 'Bawah' },
'单': { 'en-US': 'Odd', 'ms-MY': 'Ganjil' },
'双': { 'en-US': 'Even', 'ms-MY': 'Genap' },
'�: { 'en-US': 'Home', 'ms-MY': 'Rumah' },
'å®?: { 'en-US': 'Away', 'ms-MY': 'Tandang' },
'�: { 'en-US': 'Over', 'ms-MY': 'Atas' },
'å°?: { 'en-US': 'Under', 'ms-MY': 'Bawah' },
'å<EFBFBD>?: { 'en-US': 'Odd', 'ms-MY': 'Ganjil' },
'å<EFBFBD>?: { 'en-US': 'Even', 'ms-MY': 'Genap' },
'冠军': { 'en-US': 'Winner', 'ms-MY': 'Juara' },
};
@@ -109,8 +109,8 @@ function translateSel(name: string): string {
function legResultIcon(status?: string | null) {
switch (status?.toUpperCase()) {
case 'WON': return '✓';
case 'LOST': return '✗';
case 'WON': return '�;
case 'LOST': return '�;
case 'PUSH': return '=';
default: return '';
}
@@ -147,7 +147,7 @@ const displayLegs = computed(() => {
<div class="modal-container" role="dialog" aria-modal="true" :aria-label="t('bet.detail_title')">
<div class="modal-header">
<span class="modal-title">{{ t('bet.detail_title') }}</span>
<button type="button" class="modal-close" :aria-label="t('support.close')" @click="close"></button>
<button type="button" class="modal-close" :aria-label="t('support.close')" @click="close">�/button>
</div>
<div class="modal-body">
@@ -364,7 +364,7 @@ const displayLegs = computed(() => {
}
.mono {
font-family: 'SF Mono', 'Consolas', monospace;
font-family: var(--font-mono);
}
.st-badge {
@@ -465,7 +465,7 @@ const displayLegs = computed(() => {
font-size: 13px;
font-weight: 800;
color: var(--primary);
font-family: 'SF Mono', 'Consolas', monospace;
font-family: var(--font-mono);
}
.leg-result {

View File

@@ -30,7 +30,7 @@ function formatPeriod(start: string, end: string) {
const opts: Intl.DateTimeFormatOptions = { year: 'numeric', month: '2-digit', day: '2-digit' };
const s = new Date(start).toLocaleDateString(locale.value, opts);
const e = new Date(end).toLocaleDateString(locale.value, opts);
return `${s} ${e}`;
return `${s} �${e}`;
}
function formatRate(rate: string) {
@@ -40,7 +40,7 @@ function formatRate(rate: string) {
}
function formatTime(value: string | null) {
if (!value) return '—';
if (!value) return '�;
return new Date(value).toLocaleString(locale.value);
}
</script>
@@ -52,7 +52,7 @@ function formatTime(value: string | null) {
<div class="modal-container" role="dialog" aria-modal="true" :aria-label="t('cashback.title')">
<div class="modal-header">
<span class="modal-title">{{ t('cashback.title') }}</span>
<button type="button" class="modal-close" :aria-label="t('support.close')" @click="close"></button>
<button type="button" class="modal-close" :aria-label="t('support.close')" @click="close">�/button>
</div>
<div v-if="record" class="modal-body">
@@ -164,7 +164,7 @@ function formatTime(value: string | null) {
font-size: 32px;
font-weight: 800;
font-variant-numeric: tabular-nums;
font-family: 'SF Mono', 'Consolas', monospace;
font-family: var(--font-mono);
line-height: 1.1;
}
@@ -218,7 +218,7 @@ function formatTime(value: string | null) {
}
.mono {
font-family: 'SF Mono', 'Consolas', monospace;
font-family: var(--font-mono);
font-size: 12px;
}

View File

@@ -135,7 +135,7 @@ function auditNoteDisplayText(remark: { kind: 'note'; text: string }) {
<div class="modal-container" role="dialog" aria-modal="true" :aria-label="t('recharge.order_detail')">
<div class="modal-header">
<span class="modal-title">{{ t('recharge.order_detail') }}</span>
<button type="button" class="modal-close" :aria-label="t('support.close')" @click="close"></button>
<button type="button" class="modal-close" :aria-label="t('support.close')" @click="close">�/button>
</div>
<div class="modal-body">
@@ -333,7 +333,7 @@ function auditNoteDisplayText(remark: { kind: 'note'; text: string }) {
font-size: 30px;
font-weight: 800;
font-variant-numeric: tabular-nums;
font-family: 'SF Mono', 'Consolas', monospace;
font-family: var(--font-mono);
color: var(--text);
line-height: 1.1;
margin-bottom: 4px;
@@ -346,7 +346,7 @@ function auditNoteDisplayText(remark: { kind: 'note'; text: string }) {
}
.mono {
font-family: 'SF Mono', 'Consolas', monospace;
font-family: var(--font-mono);
}
.st-badge {

View File

@@ -111,7 +111,7 @@ const activeTab = computed(() => {
.site-name {
font-size: 20px;
font-weight: 800;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
font-family: var(--font-heading);
letter-spacing: 0.5px;
background: var(--primary);
-webkit-background-clip: text;

View File

@@ -119,7 +119,7 @@ function goCashbackDetail() {
<div class="modal-container" role="dialog" aria-modal="true" :aria-label="t('wallet.transaction_detail')">
<div class="modal-header">
<span class="modal-title">{{ t('wallet.transaction_detail') }}</span>
<button type="button" class="modal-close" :aria-label="t('support.close')" @click="close"></button>
<button type="button" class="modal-close" :aria-label="t('support.close')" @click="close">�/button>
</div>
<div class="modal-body">
@@ -279,7 +279,7 @@ function goCashbackDetail() {
font-size: 32px;
font-weight: 800;
font-variant-numeric: tabular-nums;
font-family: 'SF Mono', 'Consolas', monospace;
font-family: var(--font-mono);
line-height: 1.1;
}
@@ -337,7 +337,7 @@ function goCashbackDetail() {
}
.mono {
font-family: 'SF Mono', 'Consolas', monospace;
font-family: var(--font-mono);
font-size: 12px;
}

View File

@@ -2,7 +2,89 @@
Desktop Interaction System — Theme-2 Blue-White
════════════════════════════════════════════════════════════ */
/* ── Hover Cursors and active resets ── */
/* ── Global Font System ── */
/* Heading font: Russo One — titles, labels, headings, status badges, nav, section names */
.desktop-shell h1,
.desktop-shell h2,
.desktop-shell h3,
.desktop-shell h4,
.desktop-shell h5,
.desktop-shell h6,
.desktop-shell .page-title,
.desktop-shell [class*="-title"]:not(input),
.desktop-shell [class*="-header"]:not(input),
.desktop-shell [class*="-label"]:not(input),
.desktop-shell [class*="-lbl"]:not(input),
.desktop-shell [class*="-badge"]:not(input),
.desktop-shell [class*="-meta"]:not(input),
.desktop-shell [class*="-name"]:not(input),
.desktop-shell [class*="-status"]:not(input),
.desktop-shell [class*="-pick"]:not(input),
.desktop-shell [class*="-section"]:not(input),
.desktop-shell [class*="-heading"]:not(input),
.desktop-shell [class*="-nav"]:not(input),
.desktop-shell [class*="-tab"]:not(input),
.desktop-shell [class*="-tag"]:not(input),
.desktop-shell [class*="-brand"]:not(input),
.desktop-shell [class*="-league"]:not(input),
.desktop-shell [class*="-action"]:not(input),
.desktop-shell [class*="-chip"]:not(input),
.desktop-shell [class*="-scope"]:not(input),
.desktop-shell .site-name,
.desktop-shell .market-title,
.desktop-shell .market-hdr,
.desktop-shell .market-filter-label,
.desktop-shell .market-filter-chip,
.desktop-shell .score-section-title,
.desktop-shell .panel-head,
.desktop-shell .versus-row,
.desktop-shell .kickoff-time,
.desktop-shell .locked-lbl,
.desktop-shell .lbl,
.desktop-shell .label,
.desktop-shell .section-hdr,
.desktop-shell .leagues-hdr,
.desktop-shell .time-btn,
.desktop-shell .hero-sub,
.desktop-shell .lang-opt,
.desktop-shell .hero-caption,
.desktop-shell .title,
.desktop-shell .saishi,
.desktop-shell .desktop-records-status,
.desktop-shell .desktop-records-filter-group-label,
.desktop-shell .desktop-records-table th,
.desktop-shell .data-table th,
.desktop-shell .desktop-wallet-subnav-link,
.desktop-shell .desktop-records-action-btn {
font-family: var(--font-heading);
}
/* Data font: Chakra Petch / SF Mono — odds, amounts, balances, stakes, returns, numbers */
.desktop-shell [class*="odds"]:not(input),
.desktop-shell [class*="amount"]:not(input),
.desktop-shell [class*="balance"]:not(input),
.desktop-shell [class*="stat-"]:not(input),
.desktop-shell [class*="-val"]:not(input),
.desktop-shell [class*="-value"]:not(input),
.desktop-shell [class*="stake"]:not(input),
.desktop-shell [class*="return"]:not(input),
.desktop-shell [class*="-num"]:not(input),
.desktop-shell [class*="-price"]:not(input),
.desktop-shell [class*="-payout"]:not(input),
.desktop-shell [class*="-win"]:not(input),
.desktop-shell .num-cell,
.desktop-shell .id-cell,
.desktop-shell .mono,
.desktop-shell .currency,
.desktop-shell .score,
.desktop-shell .val,
.desktop-shell .order-no,
.desktop-shell .bank-card-number,
.desktop-shell .hero-counter {
font-family: var(--font-mono);
}
/* Hover Cursors and active resets ── */
.desktop-shell a,
.desktop-shell button,
.desktop-shell select,

View File

@@ -66,12 +66,12 @@ const SEL_TRANS: Record<string, Record<string, string>> = {
'主胜': { 'en-US': 'Home Win', 'ms-MY': 'Rumah Menang' },
'客胜': { 'en-US': 'Away Win', 'ms-MY': 'Tandang Menang' },
'和局': { 'en-US': 'Draw', 'ms-MY': 'Seri' },
'主': { 'en-US': 'Home', 'ms-MY': 'Rumah' },
'客': { 'en-US': 'Away', 'ms-MY': 'Tandang' },
'大': { 'en-US': 'Over', 'ms-MY': 'Atas' },
'小': { 'en-US': 'Under', 'ms-MY': 'Bawah' },
'单': { 'en-US': 'Odd', 'ms-MY': 'Ganjil' },
'双': { 'en-US': 'Even', 'ms-MY': 'Genap' },
'�: { 'en-US': 'Home', 'ms-MY': 'Rumah' },
'å®?: { 'en-US': 'Away', 'ms-MY': 'Tandang' },
'�: { 'en-US': 'Over', 'ms-MY': 'Atas' },
'å°?: { 'en-US': 'Under', 'ms-MY': 'Bawah' },
'å<EFBFBD>?: { 'en-US': 'Odd', 'ms-MY': 'Ganjil' },
'å<EFBFBD>?: { 'en-US': 'Even', 'ms-MY': 'Genap' },
'冠军': { 'en-US': 'Winner', 'ms-MY': 'Juara' },
};
@@ -90,8 +90,8 @@ function translateSel(name: string): string {
function legResultIcon(status?: string | null) {
switch (status?.toUpperCase()) {
case 'WON': return '✓';
case 'LOST': return '✗';
case 'WON': return '�;
case 'LOST': return '�;
case 'PUSH': return '=';
default: return '';
}
@@ -125,7 +125,7 @@ const displayLegs = computed(() => {
<main class="account-main">
<div class="page-header">
<button type="button" class="back-btn" @click="goBack">
{{ t('common.back') }}
â?{{ t('common.back') }}
</button>
<h1 class="page-title">{{ t('bet.detail_title') }}</h1>
</div>
@@ -304,7 +304,7 @@ const displayLegs = computed(() => {
.summary-bet-no { display: flex; flex-direction: column; gap: 4px; }
.summary-label { font-size: 11px; color: var(--text-muted); font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; }
.summary-value { font-size: 14px; font-weight: 700; color: var(--text); }
.mono { font-family: 'SF Mono', 'Consolas', monospace; letter-spacing: 0.03em; }
.mono { font-family: var(--font-mono); letter-spacing: 0.03em; }
.summary-status { display: flex; }

View File

@@ -58,7 +58,7 @@ function formatPeriod(start: string, end: string) {
const opts: Intl.DateTimeFormatOptions = { month: '2-digit', day: '2-digit' };
const s = new Date(start).toLocaleDateString(locale.value, opts);
const e = new Date(end).toLocaleDateString(locale.value, opts);
return `${s} ${e}`;
return `${s} �${e}`;
}
function formatRate(rate: string) {
@@ -68,7 +68,7 @@ function formatRate(rate: string) {
}
function formatTime(value: string | null) {
if (!value) return '—';
if (!value) return '�;
return new Date(value).toLocaleString(locale.value, {
month: '2-digit',
day: '2-digit',
@@ -206,7 +206,7 @@ onActivated(async () => {
}
.batch-cell {
font-family: 'SF Mono', Consolas, monospace;
font-family: var(--font-mono);
font-size: 12px;
color: var(--text-muted);
}

View File

@@ -112,7 +112,7 @@ const balanceDisplay = computed(() =>
<div class="bank-card-footer">
<div class="bank-card-field">
<span class="bank-card-label">{{ t('profile.username') || '持卡人' }}</span>
<span class="bank-card-label">{{ t('profile.username') || '<EFBFBD><EFBFBD>㨃鈭? }}</span>
<span class="bank-card-holder">{{ profileRaw?.username }}</span>
</div>
<div class="bank-card-field bank-card-field--center">
@@ -131,11 +131,11 @@ const balanceDisplay = computed(() =>
<div class="info-card">
<div class="info-header">{{ t('profile.account') || '韐行<EFBFBD><EFBFBD>' }}</div>
<div class="info-row">
<span class="info-label">{{ t('profile.username') || '用户名' }}</span>
<span class="info-label">{{ t('profile.username') || '<EFBFBD><EFBFBD><EFBFBD>? }}</span>
<span class="info-val">{{ profileRaw?.username }}</span>
</div>
<div class="info-row">
<span class="info-label">{{ t('profile.phone') || '手机号' }}</span>
<span class="info-label">{{ t('profile.phone') || '<EFBFBD>𧢲㦤<EFBFBD>? }}</span>
<span class="info-val">{{ profileRaw?.preferences?.phone || '-' }}</span>
</div>
<div class="info-actions">
@@ -280,7 +280,7 @@ const balanceDisplay = computed(() =>
.bank-card-number {
margin: 0;
font-family: 'SF Mono', 'Consolas', monospace;
font-family: var(--font-mono);
font-weight: 700;
color: #fff;
font-size: 38px;

View File

@@ -187,7 +187,7 @@ onActivated(fetchMethods);
<span class="detail-val">{{ selectedMethod.bankName }}</span>
</div>
<div class="detail-row">
<span class="detail-label">{{ t('recharge.account_holder') || '持卡人' }}</span>
<span class="detail-label">{{ t('recharge.account_holder') || '<EFBFBD><EFBFBD>㨃鈭? }}</span>
<span class="detail-val">{{ selectedMethod.accountHolder }}</span>
</div>
<div class="detail-row">
@@ -207,13 +207,13 @@ onActivated(fetchMethods);
<!-- Amount input -->
<div class="field">
<label class="field-label">{{ t('recharge.amount') || '充值金额' }}</label>
<label class="field-label">{{ t('recharge.amount') || '<EFBFBD><EFBFBD><EFBFBD><EFBFBD>? }}</label>
<input
v-model="amount"
type="number"
min="0"
class="field-input"
:placeholder="t('recharge.amount_placeholder') || '请输入金额'"
:placeholder="t('recharge.amount_placeholder') || '霂瑁<EFBFBD><EFBFBD>仿<EFBFBD>憸?"
/>
</div>
@@ -222,7 +222,7 @@ onActivated(fetchMethods);
<label class="field-label">{{ t('recharge.screenshot') || '銝𠹺<E98A9D><F0A0B9BA><EFBFBD><E5899B>芸㦛' }}</label>
<div v-if="screenshotPreview" class="preview-wrap">
<img :src="screenshotPreview" alt="preview" class="preview-img" />
<button type="button" class="clear-btn" @click="clearFile"></button>
<button type="button" class="clear-btn" @click="clearFile"><EFBFBD>?/button>
</div>
<label v-else class="upload-zone">
<input type="file" accept="image/*" class="hidden-input" @change="handleFileChange" />
@@ -241,7 +241,7 @@ onActivated(fetchMethods);
@click="submit"
>
<GoldSpinner v-if="submitting" :size="18" />
<span v-else>{{ t('recharge.submit') || '提交充值' }}</span>
<span v-else>{{ t('recharge.submit') || '<EFBFBD>𣂷漱<EFBFBD><EFBFBD><EFBFBD>? }}</span>
</button>
</div>
</div>
@@ -462,7 +462,7 @@ onActivated(fetchMethods);
color: var(--text);
}
.mono { font-family: 'SF Mono', 'Consolas', monospace; letter-spacing: 0.04em; }
.mono { font-family: var(--font-mono); letter-spacing: 0.04em; }
.break-all { word-break: break-all; }
.qr-wrap {

View File

@@ -71,7 +71,7 @@ function txLabel(tx: TxDetail): string {
<div class="detail-layout">
<div class="page-header">
<button type="button" class="back-btn" @click="goBack">
{{ t('common.back') || '返回' }}
â?{{ t('common.back') || 'è¿åž' }}
</button>
<h1 class="page-title">{{ t('wallet.transaction_detail') || '交易详情' }}</h1>
</div>
@@ -101,19 +101,19 @@ function txLabel(tx: TxDetail): string {
<span class="row-val">{{ txSummaryLabel(detail, t) || '-' }}</span>
</div>
<div class="detail-row">
<span class="row-label">{{ t('wallet.balance_before') || '变动前余额' }}</span>
<span class="row-label">{{ t('wallet.balance_before') || 'å<EFBFBD>˜åЍå‰<EFBFBD>ä½™é¢? }}</span>
<span class="row-val mono">{{ formatMoney(detail.balanceBefore, locale) }}</span>
</div>
<div class="detail-row">
<span class="row-label">{{ t('wallet.balance_after') || '变动后余额' }}</span>
<span class="row-label">{{ t('wallet.balance_after') || 'å<EFBFBD>˜åЍå<EFBFBD>Žä½é¢? }}</span>
<span class="row-val mono">{{ formatMoney(detail.balanceAfter, locale) }}</span>
</div>
<div v-if="parseFloat(detail.frozenBefore || '0') > 0 || parseFloat(detail.frozenAfter || '0') > 0" class="detail-row">
<span class="row-label">{{ t('wallet.frozen_before') || '冻结前' }}</span>
<span class="row-label">{{ t('wallet.frozen_before') || '冻结� }}</span>
<span class="row-val mono">{{ formatMoney(detail.frozenBefore, locale) }}</span>
</div>
<div v-if="parseFloat(detail.frozenBefore || '0') > 0 || parseFloat(detail.frozenAfter || '0') > 0" class="detail-row">
<span class="row-label">{{ t('wallet.frozen_after') || '冻结后' }}</span>
<span class="row-label">{{ t('wallet.frozen_after') || 'å»ç»å<EFBFBD>? }}</span>
<span class="row-val mono">{{ formatMoney(detail.frozenAfter, locale) }}</span>
</div>
<div class="detail-row">
@@ -121,13 +121,13 @@ function txLabel(tx: TxDetail): string {
<span class="row-val">{{ new Date(detail.createdAt).toLocaleString() }}</span>
</div>
<div class="detail-row">
<span class="row-label">{{ t('wallet.transaction_id') || '流水号' }}</span>
<span class="row-label">{{ t('wallet.transaction_id') || 'æµ<EFBFBD>æ°´å<EFBFBD>? }}</span>
<span class="row-val mono">{{ detail.transactionId }}</span>
</div>
</div>
</div>
<div v-else class="empty-state">{{ t('common.not_found') || '未找到记录' }}</div>
<div v-else class="empty-state">{{ t('common.not_found') || '未æ¾åˆ°è®°å½? }}</div>
</div>
</main>
</div>
@@ -165,7 +165,7 @@ function txLabel(tx: TxDetail): string {
font-size: 36px;
font-weight: 800;
font-variant-numeric: tabular-nums;
font-family: 'SF Mono', 'Consolas', monospace;
font-family: var(--font-mono);
line-height: 1.1;
margin-bottom: 6px;
}
@@ -197,5 +197,5 @@ function txLabel(tx: TxDetail): string {
.row-val { flex: 1; font-size: 13px; font-weight: 700; color: var(--text); word-break: break-all; }
.row-val.pos { color: var(--primary-light); }
.row-val.neg { color: var(--danger); }
.mono { font-family: 'SF Mono', 'Consolas', monospace; font-size: 12px; letter-spacing: 0.03em; }
.mono { font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.03em; }
</style>