From 8a1ba0fd95428d0692abd192f3456ae5fd7a3f34 Mon Sep 17 00:00:00 2001 From: Mars <3361409208a@gmail.com> Date: Mon, 29 Jun 2026 18:01:39 +0800 Subject: [PATCH] =?UTF-8?q?feat(player):=20=E6=96=B0=E5=A2=9E=E6=A1=8C?= =?UTF-8?q?=E9=9D=A2=E7=AB=AF=20UI=20=E4=B8=8E=E5=93=8D=E5=BA=94=E5=BC=8F?= =?UTF-8?q?=E5=8F=8C=E7=AB=AF=E8=B7=AF=E7=94=B1=E6=9E=B6=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将原移动端页面重命名为 Mobile*,新增 22 个 Desktop* 视图与 DesktopShell 布局体系 - 路由入口改为 Wrapper 视图,通过 useViewport(≥1024px)自动切换移动/桌面端 - 新增投注单面板、盘口弹层、联赛侧栏、数据表格等桌面组件及独立样式令牌 - 扩展 betSlip store、串关筛选、冠军盘、Toast/悬浮信箱等交互与三语 i18n - 公告/消息 Hub 拆分移动与桌面实现;API 投注/钱包/充值记录支持 pageSize 分页 --- .../applications/player/player.controller.ts | 8 +- apps/player/scripts/check-desktop-i18n.mjs | 44 + apps/player/src/App.vue | 2 + apps/player/src/assets/images/pcbg.webp | Bin 0 -> 38582 bytes apps/player/src/components/AppToast.vue | 47 + apps/player/src/components/BetSlipDrawer.vue | 55 +- .../player/src/components/CashBalanceChip.vue | 29 + apps/player/src/components/ConfirmDialog.vue | 3 +- .../player/src/components/FloatingMailbox.vue | 350 +++ .../src/components/HomeAnnouncementCard.vue | 248 +++ .../src/components/MessageListPanel.vue | 7 +- apps/player/src/components/TeamEmblem.vue | 16 +- .../src/components/desktop/AccountSideNav.vue | 121 + .../src/components/desktop/BetSlipPanel.vue | 1967 +++++++++++++++++ .../src/components/desktop/DataTable.vue | 123 ++ .../desktop/DesktopBanner3DCarousel.vue | 468 ++++ .../desktop/DesktopOddsBetPopover.vue | 400 ++++ .../desktop/DesktopOutrightEventCard.vue | 112 + .../src/components/desktop/DesktopShell.vue | 131 ++ .../src/components/desktop/DesktopTopNav.vue | 243 ++ .../desktop/DesktopWalletSubNav.vue | 46 + .../src/components/desktop/LeagueSidebar.vue | 319 +++ .../src/components/desktop/MatchSidebar.vue | 342 +++ .../src/components/desktop/Pagination.vue | 172 ++ .../components/desktop/SportsCategoryBar.vue | 108 + .../match-detail/CorrectScorePanel.vue | 59 +- .../match-detail/MarketSelectionsPanel.vue | 129 +- .../components/outright/OutrightBetModal.vue | 64 +- .../outright/OutrightOptionCard.vue | 2 + .../src/components/outright/OutrightPanel.vue | 63 +- apps/player/src/composables/useAppToast.ts | 23 + .../src/composables/useDesktopBetLocate.ts | 42 + .../src/composables/useDesktopBetPopover.ts | 39 + .../composables/useDesktopParlayMatches.ts | 67 + .../src/composables/useFloatingMailbox.ts | 24 + .../player/src/composables/useMatchFilters.ts | 33 + .../src/composables/useOutrightEvents.ts | 68 + apps/player/src/composables/usePlayerHome.ts | 37 + apps/player/src/composables/useViewport.ts | 28 + apps/player/src/i18n/en-US.ts | 115 +- apps/player/src/i18n/ms-MY.ts | 121 +- apps/player/src/i18n/zh-CN.ts | 119 +- apps/player/src/layouts/MainLayout.vue | 21 +- apps/player/src/main.ts | 1 + apps/player/src/router/index.ts | 30 +- apps/player/src/stores/betSlip.ts | 226 +- apps/player/src/styles.css | 7 + apps/player/src/styles/desktop/index.css | 4 + .../player/src/styles/desktop/interaction.css | 102 + apps/player/src/styles/desktop/layout.css | 184 ++ apps/player/src/styles/desktop/records.css | 309 +++ apps/player/src/styles/desktop/tokens.css | 38 + .../src/utils/betPlaceConfirmMessage.ts | 49 + .../src/views/AnnouncementDetailView.vue | 319 +-- .../player/src/views/AnnouncementListView.vue | 179 +- .../player/src/views/AnnouncementsHubView.vue | 13 + apps/player/src/views/BetDetailView.vue | 736 +----- apps/player/src/views/CashbackRecordsView.vue | 413 +--- apps/player/src/views/FootballView.vue | 784 +------ .../src/views/ForgotPasswordWrapperView.vue | 10 + apps/player/src/views/HomeView.vue | 450 +--- apps/player/src/views/InboxHubView.vue | 297 +-- apps/player/src/views/LoginWrapperView.vue | 10 + apps/player/src/views/MatchDetailView.vue | 989 +-------- apps/player/src/views/MessageDetailView.vue | 390 +--- apps/player/src/views/MessagesHubView.vue | 13 + .../views/MobileAnnouncementDetailView.vue | 440 ++++ .../src/views/MobileAnnouncementListView.vue | 327 +++ apps/player/src/views/MobileBetDetailView.vue | 734 ++++++ .../src/views/MobileCashbackRecordsView.vue | 411 ++++ apps/player/src/views/MobileFootballView.vue | 794 +++++++ apps/player/src/views/MobileHomeView.vue | 459 ++++ apps/player/src/views/MobileInboxHubView.vue | 299 +++ .../src/views/MobileMatchDetailView.vue | 989 +++++++++ .../src/views/MobileMessageDetailView.vue | 454 ++++ apps/player/src/views/MobileMyBetsView.vue | 249 +++ .../src/views/MobileOutrightDetailView.vue | 166 ++ .../src/views/MobileProfileEditView.vue | 564 +++++ apps/player/src/views/MobileProfileView.vue | 728 ++++++ .../src/views/MobileRechargeHistoryView.vue | 851 +++++++ apps/player/src/views/MobileRechargeView.vue | 691 ++++++ .../src/views/MobileWalletDetailView.vue | 387 ++++ .../MobileWalletTransactionDetailView.vue | 388 ++++ apps/player/src/views/MobileWalletView.vue | 263 +++ apps/player/src/views/MyBetsView.vue | 227 +- apps/player/src/views/OutrightDetailView.vue | 12 + apps/player/src/views/ProfileEditView.vue | 566 +---- apps/player/src/views/ProfileView.vue | 730 +----- apps/player/src/views/RechargeHistoryView.vue | 853 +------ apps/player/src/views/RechargeView.vue | 693 +----- apps/player/src/views/RegisterWrapperView.vue | 10 + apps/player/src/views/WalletDetailView.vue | 389 +--- .../src/views/WalletTransactionDetailView.vue | 390 +--- apps/player/src/views/WalletView.vue | 265 +-- .../desktop/DesktopAnnouncementDetailView.vue | 31 + .../desktop/DesktopAnnouncementListView.vue | 327 +++ .../desktop/DesktopAnnouncementsHubShell.vue | 44 + .../views/desktop/DesktopBetDetailView.vue | 189 ++ .../desktop/DesktopCashbackRecordsView.vue | 183 ++ .../src/views/desktop/DesktopFootballView.vue | 372 ++++ .../desktop/DesktopForgotPasswordView.vue | 99 + .../src/views/desktop/DesktopHomeView.vue | 355 +++ .../src/views/desktop/DesktopInboxHubView.vue | 264 +++ .../src/views/desktop/DesktopLoginView.vue | 134 ++ .../views/desktop/DesktopMatchDetailView.vue | 771 +++++++ .../views/desktop/DesktopMessagesHubShell.vue | 182 ++ .../src/views/desktop/DesktopMyBetsView.vue | 194 ++ .../desktop/DesktopOutrightDetailView.vue | 334 +++ .../views/desktop/DesktopProfileEditView.vue | 353 +++ .../src/views/desktop/DesktopProfileView.vue | 439 ++++ .../desktop/DesktopRechargeHistoryView.vue | 145 ++ .../src/views/desktop/DesktopRechargeView.vue | 580 +++++ .../src/views/desktop/DesktopRegisterView.vue | 100 + .../views/desktop/DesktopWalletDetailView.vue | 193 ++ .../DesktopWalletTransactionDetailView.vue | 201 ++ .../src/views/desktop/DesktopWalletView.vue | 155 ++ 116 files changed, 22249 insertions(+), 8693 deletions(-) create mode 100644 apps/player/scripts/check-desktop-i18n.mjs create mode 100644 apps/player/src/assets/images/pcbg.webp create mode 100644 apps/player/src/components/AppToast.vue create mode 100644 apps/player/src/components/FloatingMailbox.vue create mode 100644 apps/player/src/components/HomeAnnouncementCard.vue create mode 100644 apps/player/src/components/desktop/AccountSideNav.vue create mode 100644 apps/player/src/components/desktop/BetSlipPanel.vue create mode 100644 apps/player/src/components/desktop/DataTable.vue create mode 100644 apps/player/src/components/desktop/DesktopBanner3DCarousel.vue create mode 100644 apps/player/src/components/desktop/DesktopOddsBetPopover.vue create mode 100644 apps/player/src/components/desktop/DesktopOutrightEventCard.vue create mode 100644 apps/player/src/components/desktop/DesktopShell.vue create mode 100644 apps/player/src/components/desktop/DesktopTopNav.vue create mode 100644 apps/player/src/components/desktop/DesktopWalletSubNav.vue create mode 100644 apps/player/src/components/desktop/LeagueSidebar.vue create mode 100644 apps/player/src/components/desktop/MatchSidebar.vue create mode 100644 apps/player/src/components/desktop/Pagination.vue create mode 100644 apps/player/src/components/desktop/SportsCategoryBar.vue create mode 100644 apps/player/src/composables/useAppToast.ts create mode 100644 apps/player/src/composables/useDesktopBetLocate.ts create mode 100644 apps/player/src/composables/useDesktopBetPopover.ts create mode 100644 apps/player/src/composables/useDesktopParlayMatches.ts create mode 100644 apps/player/src/composables/useFloatingMailbox.ts create mode 100644 apps/player/src/composables/useMatchFilters.ts create mode 100644 apps/player/src/composables/useOutrightEvents.ts create mode 100644 apps/player/src/composables/useViewport.ts create mode 100644 apps/player/src/styles/desktop/index.css create mode 100644 apps/player/src/styles/desktop/interaction.css create mode 100644 apps/player/src/styles/desktop/layout.css create mode 100644 apps/player/src/styles/desktop/records.css create mode 100644 apps/player/src/styles/desktop/tokens.css create mode 100644 apps/player/src/utils/betPlaceConfirmMessage.ts create mode 100644 apps/player/src/views/AnnouncementsHubView.vue create mode 100644 apps/player/src/views/ForgotPasswordWrapperView.vue create mode 100644 apps/player/src/views/LoginWrapperView.vue create mode 100644 apps/player/src/views/MessagesHubView.vue create mode 100644 apps/player/src/views/MobileAnnouncementDetailView.vue create mode 100644 apps/player/src/views/MobileAnnouncementListView.vue create mode 100644 apps/player/src/views/MobileBetDetailView.vue create mode 100644 apps/player/src/views/MobileCashbackRecordsView.vue create mode 100644 apps/player/src/views/MobileFootballView.vue create mode 100644 apps/player/src/views/MobileHomeView.vue create mode 100644 apps/player/src/views/MobileInboxHubView.vue create mode 100644 apps/player/src/views/MobileMatchDetailView.vue create mode 100644 apps/player/src/views/MobileMessageDetailView.vue create mode 100644 apps/player/src/views/MobileMyBetsView.vue create mode 100644 apps/player/src/views/MobileOutrightDetailView.vue create mode 100644 apps/player/src/views/MobileProfileEditView.vue create mode 100644 apps/player/src/views/MobileProfileView.vue create mode 100644 apps/player/src/views/MobileRechargeHistoryView.vue create mode 100644 apps/player/src/views/MobileRechargeView.vue create mode 100644 apps/player/src/views/MobileWalletDetailView.vue create mode 100644 apps/player/src/views/MobileWalletTransactionDetailView.vue create mode 100644 apps/player/src/views/MobileWalletView.vue create mode 100644 apps/player/src/views/OutrightDetailView.vue create mode 100644 apps/player/src/views/RegisterWrapperView.vue create mode 100644 apps/player/src/views/desktop/DesktopAnnouncementDetailView.vue create mode 100644 apps/player/src/views/desktop/DesktopAnnouncementListView.vue create mode 100644 apps/player/src/views/desktop/DesktopAnnouncementsHubShell.vue create mode 100644 apps/player/src/views/desktop/DesktopBetDetailView.vue create mode 100644 apps/player/src/views/desktop/DesktopCashbackRecordsView.vue create mode 100644 apps/player/src/views/desktop/DesktopFootballView.vue create mode 100644 apps/player/src/views/desktop/DesktopForgotPasswordView.vue create mode 100644 apps/player/src/views/desktop/DesktopHomeView.vue create mode 100644 apps/player/src/views/desktop/DesktopInboxHubView.vue create mode 100644 apps/player/src/views/desktop/DesktopLoginView.vue create mode 100644 apps/player/src/views/desktop/DesktopMatchDetailView.vue create mode 100644 apps/player/src/views/desktop/DesktopMessagesHubShell.vue create mode 100644 apps/player/src/views/desktop/DesktopMyBetsView.vue create mode 100644 apps/player/src/views/desktop/DesktopOutrightDetailView.vue create mode 100644 apps/player/src/views/desktop/DesktopProfileEditView.vue create mode 100644 apps/player/src/views/desktop/DesktopProfileView.vue create mode 100644 apps/player/src/views/desktop/DesktopRechargeHistoryView.vue create mode 100644 apps/player/src/views/desktop/DesktopRechargeView.vue create mode 100644 apps/player/src/views/desktop/DesktopRegisterView.vue create mode 100644 apps/player/src/views/desktop/DesktopWalletDetailView.vue create mode 100644 apps/player/src/views/desktop/DesktopWalletTransactionDetailView.vue create mode 100644 apps/player/src/views/desktop/DesktopWalletView.vue diff --git a/apps/api/src/applications/player/player.controller.ts b/apps/api/src/applications/player/player.controller.ts index f2f52c4..ec16982 100644 --- a/apps/api/src/applications/player/player.controller.ts +++ b/apps/api/src/applications/player/player.controller.ts @@ -306,13 +306,14 @@ export class PlayerController { @CurrentUser('locale') locale: string, @Query('status') status?: string, @Query('page') page?: string, + @Query('pageSize') pageSize?: string, @Query('matchId') matchId?: string, ) { const result = await this.bets.getUserBets( userId, status, page ? parseInt(page, 10) : 1, - 20, + pageSize ? parseInt(pageSize, 10) : 20, matchId ? BigInt(matchId) : undefined, ); const items = await this.matches.enrichBetsForHistory(result.items, locale); @@ -347,9 +348,10 @@ export class PlayerController { async transactions( @CurrentUser('id') userId: bigint, @Query('page') page?: string, + @Query('pageSize') pageSize?: string, @Query('type') type?: string, ) { - const result = await this.wallet.getTransactions(userId, page ? parseInt(page) : 1, 20, type); + const result = await this.wallet.getTransactions(userId, page ? parseInt(page) : 1, pageSize ? parseInt(pageSize) : 20, type); return jsonResponse(result); } @@ -424,10 +426,12 @@ export class PlayerController { async myDepositOrders( @CurrentUser('id') userId: bigint, @Query('page') page?: string, + @Query('pageSize') pageSize?: string, ) { const result = await this.deposit.getPlayerDepositOrders( userId, page ? parseInt(page, 10) : 1, + pageSize ? parseInt(pageSize, 10) : 20, ); return jsonResponse(result); } diff --git a/apps/player/scripts/check-desktop-i18n.mjs b/apps/player/scripts/check-desktop-i18n.mjs new file mode 100644 index 0000000..25c1455 --- /dev/null +++ b/apps/player/scripts/check-desktop-i18n.mjs @@ -0,0 +1,44 @@ +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const root = path.join(__dirname, '..'); + +function flatten(obj, prefix = '') { + const out = {}; + for (const [k, v] of Object.entries(obj)) { + const key = prefix ? `${prefix}.${k}` : k; + if (v && typeof v === 'object' && !Array.isArray(v)) Object.assign(out, flatten(v, key)); + else out[key] = v; + } + return out; +} + +function extractKeysFromDir(dir) { + const keys = new Set(); + const re = /\bt\s*\(\s*['"`]([^'"`]+)['"`]/g; + function walk(d) { + for (const ent of fs.readdirSync(d, { withFileTypes: true })) { + const p = path.join(d, ent.name); + if (ent.isDirectory()) walk(p); + else if (ent.name.endsWith('.vue')) { + const src = fs.readFileSync(p, 'utf8'); + let m; + while ((m = re.exec(src))) keys.add(m[1]); + } + } + } + walk(dir); + return keys; +} + +const zhMod = await import('../src/i18n/zh-CN.ts'); +const zh = flatten(zhMod.default); +const dirs = ['src/views/desktop', 'src/components/desktop'].map((d) => path.join(root, d)); +const used = new Set(); +for (const d of dirs) extractKeysFromDir(d).forEach((k) => used.add(k)); + +const missing = [...used].filter((k) => !(k in zh)).sort(); +console.log(`Missing keys (${missing.length}):`); +missing.forEach((k) => console.log(` ${k}`)); diff --git a/apps/player/src/App.vue b/apps/player/src/App.vue index f4ac569..4acb453 100644 --- a/apps/player/src/App.vue +++ b/apps/player/src/App.vue @@ -1,8 +1,10 @@ diff --git a/apps/player/src/assets/images/pcbg.webp b/apps/player/src/assets/images/pcbg.webp new file mode 100644 index 0000000000000000000000000000000000000000..693abbc8125b587714193e7b23b7d8511cdf8236 GIT binary patch literal 38582 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

sVv$q(;GLSpm)3!4GU5#vJKTM#?WdTOC@B# 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 SPyms~w?sziZ@>Tm0000AiN1dT literal 0 HcmV?d00001 diff --git a/apps/player/src/components/AppToast.vue b/apps/player/src/components/AppToast.vue new file mode 100644 index 0000000..6b68d8c --- /dev/null +++ b/apps/player/src/components/AppToast.vue @@ -0,0 +1,47 @@ + + + + + diff --git a/apps/player/src/components/BetSlipDrawer.vue b/apps/player/src/components/BetSlipDrawer.vue index fe166bc..11d295d 100644 --- a/apps/player/src/components/BetSlipDrawer.vue +++ b/apps/player/src/components/BetSlipDrawer.vue @@ -11,8 +11,10 @@ import { import { useAuthStore } from '../stores/auth'; import { formatMoney, parseAmount } from '../utils/localeDisplay'; import BetSuccessOverlay from './BetSuccessOverlay.vue'; +import ConfirmDialog from './ConfirmDialog.vue'; import api from '../api'; import { usePlayerProfile } from '../composables/usePlayerProfile'; +import { buildBetPlaceConfirmMessage } from '../utils/betPlaceConfirmMessage'; const props = defineProps<{ modelValue: boolean }>(); const emit = defineEmits<{ 'update:modelValue': [boolean] }>(); @@ -33,6 +35,8 @@ const balance = ref(null); const error = ref(''); const success = ref(''); const showSuccess = ref(false); +const showPlaceConfirm = ref(false); +const placeConfirmMessage = ref(''); const MIN_STAKE = 5; const MAX_STAKE_INTEGER_LENGTH = 9; const stakeInput = ref(''); @@ -345,34 +349,54 @@ function oddsTrendClass(delta: OddsDelta) { return delta.newOdds >= delta.oldOdds ? 'odds-up' : 'odds-down'; } -async function placeBet() { - if (!activeItems.value.length) return; +function validatePlaceBet(): boolean { + if (!activeItems.value.length) return false; if (!auth.token) { auth.showLoginPrompt(); - return; + return false; } if (slip.stake < MIN_STAKE) { error.value = t('bet.slip_min_error', { amount: MIN_STAKE }); - return; + return false; } if (balance.value != null && slip.stake > balance.value) { error.value = t('bet.outright_insufficient'); - return; + return false; } if (activeTab.value === 'parlay' && !canSubmitActive.value) { error.value = slip.parlayItems.length > PARLAY_MAX_LEGS ? t('bet.parlay_max_legs') : t('bet.parlay_need_more'); - return; + return false; } if (hasSuspendedSelections.value) { error.value = t('bet.odds_suspended'); - return; + return false; } + return true; +} + +function onPlaceBetClick() { + error.value = ''; + if (!validatePlaceBet()) return; if (hasPendingOddsChanges.value) { acceptPendingOdds(); } + const items = activeTab.value === 'parlay' ? [...slip.parlayItems] : activeItems.value; + placeConfirmMessage.value = buildBetPlaceConfirmMessage(t, { + mode: activeTab.value, + items, + totalStake: Number(slip.stake) || 0, + totalReturn: activeEstimatedReturn.value, + totalOdds: activeTab.value === 'parlay' ? activeTotalOdds.value : undefined, + formatMoney: (amount) => formatMoney(amount, locale.value), + getStake: () => Number(slip.stake) || 0, + getOdds: (item) => effectiveOdds(item), + }); + showPlaceConfirm.value = true; +} +async function executePlaceBet() { loading.value = true; error.value = ''; success.value = ''; @@ -414,6 +438,11 @@ async function placeBet() { } } +async function confirmPlaceBet() { + showPlaceConfirm.value = false; + await executePlaceBet(); +} + watch( () => props.modelValue, (open) => { @@ -622,7 +651,7 @@ watch( type="button" class="btn-primary" :disabled="loading || !canSubmitWithOdds" - @click="placeBet" + @click="onPlaceBetClick" > {{ submitButtonLabel }} @@ -630,6 +659,16 @@ watch( + + diff --git a/apps/player/src/components/CashBalanceChip.vue b/apps/player/src/components/CashBalanceChip.vue index d104b25..6a42e6f 100644 --- a/apps/player/src/components/CashBalanceChip.vue +++ b/apps/player/src/components/CashBalanceChip.vue @@ -76,6 +76,9 @@ onUnmounted(() => { +

@@ -105,6 +108,32 @@ onUnmounted(() => { .cash-chip-wrap { position: relative; z-index: 120; + display: flex; + align-items: center; + gap: 6px; +} + +.direct-recharge-btn { + height: 36px; + padding: 0 12px; + border-radius: 6px; + background: var(--primary); + color: var(--tertiary); + font-size: 13px; + font-weight: 700; + border: none; + cursor: pointer; + white-space: nowrap; +} + +.direct-recharge-btn:active { + opacity: 0.8; +} + +@media (max-width: 1023px) { + .direct-recharge-btn { + display: none; + } } .cash-chip { diff --git a/apps/player/src/components/ConfirmDialog.vue b/apps/player/src/components/ConfirmDialog.vue index 9dc1d3e..e2422ba 100644 --- a/apps/player/src/components/ConfirmDialog.vue +++ b/apps/player/src/components/ConfirmDialog.vue @@ -89,7 +89,7 @@ function onConfirm() { .confirm-overlay { position: fixed; inset: 0; - z-index: 1000; + z-index: 1100; display: flex; align-items: center; justify-content: center; @@ -125,6 +125,7 @@ function onConfirm() { line-height: 1.6; color: #c8c8c8; text-align: center; + white-space: pre-line; } .confirm-actions { diff --git a/apps/player/src/components/FloatingMailbox.vue b/apps/player/src/components/FloatingMailbox.vue new file mode 100644 index 0000000..331f457 --- /dev/null +++ b/apps/player/src/components/FloatingMailbox.vue @@ -0,0 +1,350 @@ + + + + + diff --git a/apps/player/src/components/HomeAnnouncementCard.vue b/apps/player/src/components/HomeAnnouncementCard.vue new file mode 100644 index 0000000..f7ef060 --- /dev/null +++ b/apps/player/src/components/HomeAnnouncementCard.vue @@ -0,0 +1,248 @@ + + + + + diff --git a/apps/player/src/components/MessageListPanel.vue b/apps/player/src/components/MessageListPanel.vue index a93d947..5c65d25 100644 --- a/apps/player/src/components/MessageListPanel.vue +++ b/apps/player/src/components/MessageListPanel.vue @@ -12,6 +12,9 @@ import { stripHtml } from '../utils/html'; const router = useRouter(); const { t, locale } = useI18n(); const auth = useAuthStore(); +const emit = defineEmits<{ + (e: 'click-message', id: string): void; +}>(); const { messages, loading, @@ -50,7 +53,7 @@ function messagePreview(item: PlayerMessage) { } function openDetail(id: string) { - router.push(`/messages/${id}`); + emit('click-message', id); } async function fetchPage(nextPage: number, append = false) { @@ -178,8 +181,6 @@ onActivated(tryLoad); diff --git a/apps/player/src/components/desktop/AccountSideNav.vue b/apps/player/src/components/desktop/AccountSideNav.vue new file mode 100644 index 0000000..748611d --- /dev/null +++ b/apps/player/src/components/desktop/AccountSideNav.vue @@ -0,0 +1,121 @@ + + + + + diff --git a/apps/player/src/components/desktop/BetSlipPanel.vue b/apps/player/src/components/desktop/BetSlipPanel.vue new file mode 100644 index 0000000..6f364ec --- /dev/null +++ b/apps/player/src/components/desktop/BetSlipPanel.vue @@ -0,0 +1,1967 @@ + + + + + diff --git a/apps/player/src/components/desktop/DataTable.vue b/apps/player/src/components/desktop/DataTable.vue new file mode 100644 index 0000000..4df4261 --- /dev/null +++ b/apps/player/src/components/desktop/DataTable.vue @@ -0,0 +1,123 @@ + + + + + diff --git a/apps/player/src/components/desktop/DesktopBanner3DCarousel.vue b/apps/player/src/components/desktop/DesktopBanner3DCarousel.vue new file mode 100644 index 0000000..c03d518 --- /dev/null +++ b/apps/player/src/components/desktop/DesktopBanner3DCarousel.vue @@ -0,0 +1,468 @@ + + + + + diff --git a/apps/player/src/components/desktop/DesktopOddsBetPopover.vue b/apps/player/src/components/desktop/DesktopOddsBetPopover.vue new file mode 100644 index 0000000..c933bae --- /dev/null +++ b/apps/player/src/components/desktop/DesktopOddsBetPopover.vue @@ -0,0 +1,400 @@ + + + + + diff --git a/apps/player/src/components/desktop/DesktopOutrightEventCard.vue b/apps/player/src/components/desktop/DesktopOutrightEventCard.vue new file mode 100644 index 0000000..9bc9501 --- /dev/null +++ b/apps/player/src/components/desktop/DesktopOutrightEventCard.vue @@ -0,0 +1,112 @@ + + + + + diff --git a/apps/player/src/components/desktop/DesktopShell.vue b/apps/player/src/components/desktop/DesktopShell.vue new file mode 100644 index 0000000..1ed6b87 --- /dev/null +++ b/apps/player/src/components/desktop/DesktopShell.vue @@ -0,0 +1,131 @@ + + + diff --git a/apps/player/src/components/desktop/DesktopTopNav.vue b/apps/player/src/components/desktop/DesktopTopNav.vue new file mode 100644 index 0000000..fb4d940 --- /dev/null +++ b/apps/player/src/components/desktop/DesktopTopNav.vue @@ -0,0 +1,243 @@ + + + + + diff --git a/apps/player/src/components/desktop/DesktopWalletSubNav.vue b/apps/player/src/components/desktop/DesktopWalletSubNav.vue new file mode 100644 index 0000000..db241ef --- /dev/null +++ b/apps/player/src/components/desktop/DesktopWalletSubNav.vue @@ -0,0 +1,46 @@ + + + diff --git a/apps/player/src/components/desktop/LeagueSidebar.vue b/apps/player/src/components/desktop/LeagueSidebar.vue new file mode 100644 index 0000000..fec7edf --- /dev/null +++ b/apps/player/src/components/desktop/LeagueSidebar.vue @@ -0,0 +1,319 @@ + + + + + diff --git a/apps/player/src/components/desktop/MatchSidebar.vue b/apps/player/src/components/desktop/MatchSidebar.vue new file mode 100644 index 0000000..1a77efd --- /dev/null +++ b/apps/player/src/components/desktop/MatchSidebar.vue @@ -0,0 +1,342 @@ + + + + + diff --git a/apps/player/src/components/desktop/Pagination.vue b/apps/player/src/components/desktop/Pagination.vue new file mode 100644 index 0000000..253f4a9 --- /dev/null +++ b/apps/player/src/components/desktop/Pagination.vue @@ -0,0 +1,172 @@ + + + + + diff --git a/apps/player/src/components/desktop/SportsCategoryBar.vue b/apps/player/src/components/desktop/SportsCategoryBar.vue new file mode 100644 index 0000000..a48786e --- /dev/null +++ b/apps/player/src/components/desktop/SportsCategoryBar.vue @@ -0,0 +1,108 @@ + + + + + diff --git a/apps/player/src/components/match-detail/CorrectScorePanel.vue b/apps/player/src/components/match-detail/CorrectScorePanel.vue index 5e38d01..ce07e18 100644 --- a/apps/player/src/components/match-detail/CorrectScorePanel.vue +++ b/apps/player/src/components/match-detail/CorrectScorePanel.vue @@ -15,10 +15,12 @@ const props = defineProps<{ }>; isSelected: (id: string) => boolean; locked?: boolean; + /** PC 全宽紧凑:更小单元格、三列均分 */ + dense?: boolean; }>(); const emit = defineEmits<{ - pick: [id: string]; + pick: [id: string, event?: MouseEvent]; }>(); const { t } = useI18n(); @@ -34,9 +36,9 @@ const columns = computed(() => ), ); -function onPick(sel: CsSelection) { +function onPick(sel: CsSelection, event?: MouseEvent) { if (props.locked) return; - emit('pick', sel.id); + emit('pick', sel.id, event); } function formatOdds(odds: string) { @@ -46,7 +48,7 @@ function formatOdds(odds: string) {