This commit is contained in:
wchino
2026-06-13 17:38:25 +08:00
parent e7e938f261
commit 7b33d9f9fa
190 changed files with 23222 additions and 4336 deletions

View File

@@ -7,6 +7,10 @@ import api from '../../api';
import MatchArchiveDialog from '../../components/MatchArchiveDialog.vue';
import { ensureLeagueExpanded } from '../../utils/matchesListState';
import { formatAmount } from '../../utils/format-amount';
import {
formatPlatformMatchDateTime,
platformPickerDateTimeToIso,
} from '@thebet365/shared';
const props = defineProps<{
leagueId: string;
filterStatus: string;
@@ -180,7 +184,7 @@ function matchId(row: unknown) {
return String(rowOf(row).id ?? '');
}
function matchTime(row: unknown) {
return new Date(String(rowOf(row).startTime)).toLocaleString();
return formatPlatformMatchDateTime(String(rowOf(row).startTime), locale.value);
}
function betCount(row: unknown) {
return Number(rowOf(row).betCount ?? 0);
@@ -260,6 +264,13 @@ async function promptReopenKickoff(): Promise<string | null> {
},
t('match.reopen_kickoff_hint'),
),
h(
'p',
{
style: 'margin: 0 0 12px; font-size: 12px; color: var(--el-text-color-secondary)',
},
t('match.timezone.platform_hint'),
),
h(ElDatePicker, {
modelValue: kickoff.value,
'onUpdate:modelValue': (v: string) => {
@@ -275,7 +286,8 @@ async function promptReopenKickoff(): Promise<string | null> {
cancelButtonText: t('common.cancel'),
beforeClose: (action, _instance, done) => {
if (action === 'confirm') {
if (!kickoff.value || new Date(kickoff.value) <= new Date()) {
const iso = kickoff.value ? platformPickerDateTimeToIso(kickoff.value) : '';
if (!iso || Number.isNaN(new Date(iso).getTime()) || new Date(iso) <= new Date()) {
ElMessage.warning(t('match.reopen_kickoff_invalid'));
return;
}
@@ -283,7 +295,7 @@ async function promptReopenKickoff(): Promise<string | null> {
done();
},
});
return kickoff.value || null;
return kickoff.value ? platformPickerDateTimeToIso(kickoff.value) : null;
} catch {
return null;
}
@@ -316,6 +328,11 @@ defineExpose({ reload: load });
<template>
<div class="league-matches-panel">
<div class="nested-panel-toolbar">
<el-button type="primary" size="small" @click.stop="emit('add-match')">
{{ t('match.create_fixture_btn') }}
</el-button>
</div>
<el-table v-loading="loading" :data="matches" stripe row-key="id" class="nested-match-table">
<el-table-column prop="id" label="ID" width="64" />
<el-table-column :label="t('match.col.matchup')" min-width="180">
@@ -328,7 +345,7 @@ defineExpose({ reload: load });
<el-tag :type="matchStatusType(row)" size="small">{{ matchStatusLabel(row) }}</el-tag>
</template>
</el-table-column>
<el-table-column :label="t('match.col.kickoff')" min-width="150">
<el-table-column :label="t('match.col.kickoff')" min-width="190">
<template #default="{ row }">{{ matchTime(row) }}</template>
</el-table-column>
<el-table-column :label="t('match.col.bet_count')" width="72" align="center">
@@ -347,18 +364,15 @@ defineExpose({ reload: load });
<span v-else class="bet-stat-zero">0</span>
</template>
</el-table-column>
<el-table-column width="460" align="center">
<el-table-column width="256" align="center">
<template #header>
<div class="actions-col-header">
<span class="actions-col-header__label">{{ t('common.actions') }}</span>
<el-button type="primary" size="small" @click.stop="emit('add-match')">
{{ t('match.create_fixture_btn') }}
</el-button>
</div>
</template>
<template #default="{ row }">
<div class="action-btns">
<div class="action-group">
<div class="action-row action-row--primary">
<el-button
size="small"
type="primary"
@@ -371,13 +385,12 @@ defineExpose({ reload: load });
size="small"
type="primary"
plain
class="action-btn--markets"
:disabled="!canManage(row)"
@click="openMarkets(matchId(row))"
>
{{ t('match.btn.markets') }}
</el-button>
</div>
<div class="action-group">
<el-button
v-if="canPublishRow(row)"
size="small"
@@ -394,6 +407,8 @@ defineExpose({ reload: load });
>
{{ t('match.btn.unpublish') }}
</el-button>
</div>
<div class="action-row action-row--workflow">
<el-button
size="small"
type="warning"
@@ -419,15 +434,15 @@ defineExpose({ reload: load });
>
{{ settleButtonLabel(row) }}
</el-button>
<el-button
size="small"
type="danger"
plain
@click="confirmDelete(row)"
>
{{ t('common.delete') }}
</el-button>
</div>
<el-button
size="small"
type="danger"
plain
@click="confirmDelete(row)"
>
{{ t('common.delete') }}
</el-button>
</div>
</template>
</el-table-column>
@@ -456,8 +471,17 @@ defineExpose({ reload: load });
<style scoped>
.league-matches-panel {
width: min(100%, calc(100vw - 272px));
max-width: calc(100vw - 272px);
padding: 10px 12px 12px;
background: #0a0a0a;
overflow: hidden;
background: #fbfaf7;
}
.nested-panel-toolbar {
display: flex;
justify-content: flex-end;
gap: 8px;
margin-bottom: 8px;
}
.nested-pager {
display: flex;
@@ -477,8 +501,8 @@ defineExpose({ reload: load });
.actions-col-header__label {
font-size: 12px;
font-weight: 600;
color: #aaa;
font-weight: 700;
color: var(--text-muted);
line-height: 1;
}
@@ -502,43 +526,70 @@ defineExpose({ reload: load });
}
.empty-hint {
font-size: 12px;
color: #666;
color: var(--text-muted);
margin: 8px 0 0;
}
.matchup-link {
color: var(--green-text);
color: var(--primary-link);
}
.bet-stat-active {
color: var(--green-text);
color: var(--success-text);
font-weight: 600;
}
.bet-stat-zero {
color: #555;
color: #aaa49a;
}
.action-btns {
display: flex;
flex-wrap: wrap;
display: grid;
grid-template-rows: repeat(2, 26px);
align-items: center;
gap: 6px 8px;
justify-content: center;
gap: 6px;
min-width: 0;
}
.action-group {
display: inline-flex;
flex-wrap: wrap;
gap: 4px;
.action-row {
display: inline-grid;
grid-auto-flow: column;
grid-auto-columns: max-content;
align-items: center;
justify-content: center;
gap: 5px;
min-width: 0;
padding: 2px 4px;
border-radius: 8px;
background: rgba(255, 255, 255, 0.02);
border: 1px solid rgba(255, 255, 255, 0.05);
background: #ffffff;
border: 1px solid var(--border-soft);
}
.action-row--primary {
background: #fbfaf7;
}
.action-row--workflow {
background: #ffffff;
}
.action-btns :deep(.el-button) {
margin: 0 !important;
min-width: 52px;
padding: 4px 10px !important;
min-width: 48px;
height: 22px !important;
min-height: 22px !important;
padding: 0 9px !important;
font-size: 12px !important;
line-height: 1 !important;
border-radius: 6px;
}
.action-btns :deep(.action-btn--markets:not(.is-disabled):not(:disabled)) {
background: var(--info-bg) !important;
border-color: var(--info-border) !important;
color: var(--info-text) !important;
}
.action-btns :deep(.action-btn--markets:not(.is-disabled):not(:disabled):hover),
.action-btns :deep(.action-btn--markets:not(.is-disabled):not(:disabled):focus) {
background: #d5ecfb !important;
border-color: #9fd0ed !important;
color: #155b86 !important;
}
.action-btns :deep(.el-button:not(.is-disabled):not(:disabled)) {
cursor: pointer;
}
@@ -547,4 +598,21 @@ defineExpose({ reload: load });
.action-btns :deep(.el-button:disabled) {
cursor: not-allowed;
}
@media (max-width: 760px) {
.league-matches-panel {
width: calc(100vw - 32px);
max-width: calc(100vw - 32px);
overflow-x: auto;
}
.nested-panel-toolbar,
.nested-pager {
justify-content: flex-start;
}
.action-btns {
justify-content: flex-start;
}
}
</style>