feat: 前台匿名浏览、登录引导、客服入口与返水增强
前台: - 未登录可浏览首页/赛事/赔率,下注等操作弹出登录引导(去登录/继续浏览) - 顶部新增客服入口与 iframe 弹窗 - 登录页支持暂不登录返回浏览 API: - 首页/赛事/冠军盘接口改为公开访问,支持 X-Locale 头 - JWT 守卫支持可选认证 返水: - 注单新增 is_cashbacked 字段,发放时自动标记 - 预览展示玩家余额,明确平台直发不从代理扣款 - 后台注单列表与玩家历史展示回水状态 其他: - 串关禁止同场重复选号(SAME_MATCH) - 补充结算资金流分析文档 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -8,12 +8,28 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
JSON.parse(localStorage.getItem('user') || 'null'),
|
||||
);
|
||||
|
||||
const loginPromptVisible = ref(false);
|
||||
const loginReturnTo = ref('');
|
||||
|
||||
function showLoginPrompt(returnTo?: string) {
|
||||
loginReturnTo.value = returnTo || '';
|
||||
loginPromptVisible.value = true;
|
||||
}
|
||||
|
||||
function hideLoginPrompt() {
|
||||
loginPromptVisible.value = false;
|
||||
}
|
||||
|
||||
async function login(username: string, password: string) {
|
||||
const { data } = await api.post('/player/auth/login', { username, password });
|
||||
token.value = data.data.token;
|
||||
user.value = data.data.user;
|
||||
localStorage.setItem('token', token.value);
|
||||
localStorage.setItem('user', JSON.stringify(user.value));
|
||||
const returnTo = loginReturnTo.value;
|
||||
loginReturnTo.value = '';
|
||||
loginPromptVisible.value = false;
|
||||
return returnTo;
|
||||
}
|
||||
|
||||
function logout() {
|
||||
@@ -23,5 +39,9 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
localStorage.removeItem('user');
|
||||
}
|
||||
|
||||
return { token, user, login, logout };
|
||||
return {
|
||||
token, user, login, logout,
|
||||
loginPromptVisible, loginReturnTo,
|
||||
showLoginPrompt, hideLoginPrompt,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -50,7 +50,7 @@ export const useBetSlipStore = defineStore('betSlip', () => {
|
||||
items.value.push(item);
|
||||
}
|
||||
|
||||
/** 串关页:同场/跨场均可多选,合成一张串关单 */
|
||||
/** 串关页:须为不同赛事,每场最多 1 项 */
|
||||
function addParlayLeg(item: SlipItem): ParlayRejectReason | 'MAX_LEGS' | null {
|
||||
if (mode.value === 'single') items.value = [];
|
||||
mode.value = 'parlay';
|
||||
@@ -62,6 +62,11 @@ export const useBetSlipStore = defineStore('betSlip', () => {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (items.value.some((i) => i.matchId === item.matchId)) {
|
||||
lastParlayError.value = 'SAME_MATCH';
|
||||
return 'SAME_MATCH';
|
||||
}
|
||||
|
||||
const check = canSelectForParlay({
|
||||
marketType: item.marketType,
|
||||
lineValue: parseLineValue(item.lineValue),
|
||||
@@ -115,7 +120,8 @@ export const useBetSlipStore = defineStore('betSlip', () => {
|
||||
() =>
|
||||
mode.value === 'parlay' &&
|
||||
items.value.length >= PARLAY_MIN_LEGS &&
|
||||
items.value.length <= PARLAY_MAX_LEGS,
|
||||
items.value.length <= PARLAY_MAX_LEGS &&
|
||||
!hasSameMatch.value,
|
||||
);
|
||||
|
||||
/** 详情页等同场多笔单关(串关模式不走此路径) */
|
||||
|
||||
Reference in New Issue
Block a user