feat(player): 新增桌面端 UI 与响应式双端路由架构
- 将原移动端页面重命名为 Mobile*,新增 22 个 Desktop* 视图与 DesktopShell 布局体系 - 路由入口改为 Wrapper 视图,通过 useViewport(≥1024px)自动切换移动/桌面端 - 新增投注单面板、盘口弹层、联赛侧栏、数据表格等桌面组件及独立样式令牌 - 扩展 betSlip store、串关筛选、冠军盘、Toast/悬浮信箱等交互与三语 i18n - 公告/消息 Hub 拆分移动与桌面实现;API 投注/钱包/充值记录支持 pageSize 分页
This commit is contained in:
@@ -6,6 +6,8 @@ import { usePlayerProfile } from '../../composables/usePlayerProfile';
|
||||
import { formatMoney, parseAmount } from '../../utils/localeDisplay';
|
||||
import { teamFlagUrl } from '../../utils/teamFlag';
|
||||
import BetSuccessOverlay from '../BetSuccessOverlay.vue';
|
||||
import ConfirmDialog from '../ConfirmDialog.vue';
|
||||
import { buildBetPlaceConfirmMessage } from '../../utils/betPlaceConfirmMessage';
|
||||
|
||||
export interface OutrightPick {
|
||||
selectionId: string;
|
||||
@@ -51,6 +53,8 @@ const balance = ref(0);
|
||||
const successBalance = ref(0);
|
||||
const successStake = ref(0);
|
||||
const showSuccess = ref(false);
|
||||
const showPlaceConfirm = ref(false);
|
||||
const placeConfirmMessage = ref('');
|
||||
const currentOdds = ref('');
|
||||
const currentOddsVersion = ref('');
|
||||
const oddsDelta = ref<OddsDelta | null>(null);
|
||||
@@ -209,19 +213,54 @@ function setMaxStake() {
|
||||
if (balance.value > 0) setStake(balance.value);
|
||||
}
|
||||
|
||||
async function submit() {
|
||||
if (!props.pick || stake.value <= 0) return;
|
||||
function validateSubmit(): boolean {
|
||||
if (!props.pick || stake.value <= 0) return false;
|
||||
if (stake.value > balance.value) {
|
||||
error.value = t('bet.outright_insufficient');
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
if (hasSuspendedSelection.value) {
|
||||
error.value = t('bet.odds_suspended');
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function onSubmitClick() {
|
||||
if (!props.pick) return;
|
||||
if (!validateSubmit()) return;
|
||||
if (hasPendingOddsChanges.value) {
|
||||
acceptPendingOdds();
|
||||
}
|
||||
placeConfirmMessage.value = buildBetPlaceConfirmMessage(t, {
|
||||
mode: 'single',
|
||||
items: [
|
||||
{
|
||||
selectionId: props.pick.selectionId,
|
||||
oddsVersion: currentOddsVersion.value,
|
||||
matchId: '',
|
||||
matchName: props.pick.eventTitle,
|
||||
marketId: '',
|
||||
marketName: props.pick.eventTitle,
|
||||
selectionName: `${props.pick.teamName} · ${props.pick.eventTitle}`,
|
||||
odds: oddsNum.value,
|
||||
marketType: 'OUTRIGHT',
|
||||
lineValue: null,
|
||||
allowSingle: true,
|
||||
allowParlay: false,
|
||||
},
|
||||
],
|
||||
totalStake: stake.value,
|
||||
totalReturn: estReturn.value,
|
||||
formatMoney: (amount) => formatMoney(amount, locale.value),
|
||||
getStake: () => stake.value,
|
||||
getOdds: () => oddsNum.value,
|
||||
});
|
||||
showPlaceConfirm.value = true;
|
||||
}
|
||||
|
||||
async function executeSubmit() {
|
||||
if (!props.pick || stake.value <= 0) return;
|
||||
|
||||
loading.value = true;
|
||||
error.value = '';
|
||||
@@ -251,6 +290,11 @@ async function submit() {
|
||||
}
|
||||
}
|
||||
|
||||
async function confirmSubmit() {
|
||||
showPlaceConfirm.value = false;
|
||||
await executeSubmit();
|
||||
}
|
||||
|
||||
function formatOdds(odds: string) {
|
||||
const n = parseFloat(odds);
|
||||
return Number.isFinite(n) ? n.toFixed(2) : odds;
|
||||
@@ -326,7 +370,7 @@ function formatOdds(odds: string) {
|
||||
type="button"
|
||||
class="btn-confirm btn-gold-outline"
|
||||
:disabled="loading || stake <= 0 || hasSuspendedSelection"
|
||||
@click="submit"
|
||||
@click="onSubmitClick"
|
||||
>
|
||||
{{ submitButtonLabel }}
|
||||
</button>
|
||||
@@ -364,6 +408,16 @@ function formatOdds(odds: string) {
|
||||
</div>
|
||||
|
||||
<BetSuccessOverlay :show="showSuccess" @done="showSuccess = false" />
|
||||
|
||||
<ConfirmDialog
|
||||
v-model:visible="showPlaceConfirm"
|
||||
:title="t('bet.place_confirm_title')"
|
||||
:message="placeConfirmMessage"
|
||||
:confirm-text="t('bet.place_bet')"
|
||||
:cancel-text="t('common.cancel')"
|
||||
:loading="loading"
|
||||
@confirm="confirmSubmit"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
Reference in New Issue
Block a user