feat(auth): 添加登出功能并优化认证处理

- 添加了登出相关的API端点和常量定义
- 实现了登出功能及密码验证登出逻辑
- 添加了登出会话清理和浏览器存储清除
- 在用户信息模态框中集成了登出按钮
- 添加了登出相关的国际化翻译
- 优化了API客户端中的认证错误处理
- 实现了无效令牌的自动处理机制
- 更新了GitNexus索引统计数据
- 修改了构建输出目录配置
- 清理了不必要的注释和代码
- 调整了移动端头部组件结构
- 优化了游戏历史记录查询逻辑
- 添加了控制台日志用于调试
- 设置默认注册邀请码为D97DBC16
- 在.gitignore中添加构建产物忽略规则
This commit is contained in:
JiaJun
2026-05-29 16:26:35 +08:00
parent dbfe5701aa
commit 15c519a42c
26 changed files with 527 additions and 87 deletions

View File

@@ -38,14 +38,18 @@ export function useGameHistoryVm() {
const { i18n, t } = useTranslation()
const accessToken = useAuthStore((state) => state.accessToken)
const authStatus = useAuthStore((state) => state.status)
const roundId = useGameRoundStore((state) => state.round.id)
const winningCellId = useGameRoundStore((state) => state.round.winningCellId)
const lastOpenedRoundRef = useRef<string | null>(null)
const revealPhase = useGameRoundStore((state) => state.revealAnimation.phase)
const revealRoundId = useGameRoundStore(
(state) => state.revealAnimation.roundId,
)
const lastRevealedRoundRef = useRef<string | null>(null)
const query = useInfiniteQuery({
queryKey: ['game', 'bet-my-orders', accessToken],
enabled: authStatus === 'authenticated' && Boolean(accessToken),
initialPageParam: 1,
refetchOnMount: 'always',
staleTime: 0,
queryFn: ({ pageParam }) =>
getGameBetMyOrders({
page: pageParam,
@@ -63,72 +67,62 @@ export function useGameHistoryVm() {
const items = useMemo(
() =>
(query.data?.pages ?? []).flatMap((page) =>
page.list.map((entry) => ({
amountLabel: entry.total_amount,
createdAtLabel: formatCreatedTime(
entry.create_time,
i18n.resolvedLanguage ?? 'en-US',
),
id: entry.order_no,
resultState:
entry.result_number === null
? ('pending' satisfies HistoryResultState)
: entry.numbers.includes(entry.result_number)
? ('win' satisfies HistoryResultState)
: ('lost' satisfies HistoryResultState),
numbersLabel: formatNumbers(entry.numbers),
numbers: entry.numbers,
orderNo: entry.order_no,
periodNo: entry.period_no,
resultNumberLabel:
entry.result_number === null
? '--'
: String(entry.result_number).padStart(2, '0'),
winAmountLabel: entry.win_amount,
})),
page.list.map((entry) => {
const shouldHideResult =
entry.period_no === revealRoundId && revealPhase !== 'result'
const resultNumber = shouldHideResult ? null : entry.result_number
return {
amountLabel: entry.total_amount,
createdAtLabel: formatCreatedTime(
entry.create_time,
i18n.resolvedLanguage ?? 'en-US',
),
id: entry.order_no,
resultState:
resultNumber === null
? ('pending' satisfies HistoryResultState)
: entry.numbers.includes(resultNumber)
? ('win' satisfies HistoryResultState)
: ('lost' satisfies HistoryResultState),
numbersLabel: formatNumbers(entry.numbers),
numbers: entry.numbers,
orderNo: entry.order_no,
periodNo: entry.period_no,
resultNumberLabel:
resultNumber === null
? '--'
: String(resultNumber).padStart(2, '0'),
winAmountLabel: entry.win_amount,
}
}),
),
[i18n.resolvedLanguage, query.data?.pages],
[i18n.resolvedLanguage, query.data?.pages, revealPhase, revealRoundId],
)
useEffect(() => {
const openedRoundKey =
winningCellId === null || roundId.length === 0
? null
: `${roundId}:${winningCellId}`
if (openedRoundKey === null) {
if (revealPhase !== 'result' || !revealRoundId) {
return
}
if (lastOpenedRoundRef.current === null) {
lastOpenedRoundRef.current = openedRoundKey
if (lastRevealedRoundRef.current === revealRoundId) {
return
}
if (lastOpenedRoundRef.current === openedRoundKey) {
if (authStatus !== 'authenticated' || query.isFetching || query.isLoading) {
return
}
lastOpenedRoundRef.current = openedRoundKey
if (
authStatus !== 'authenticated' ||
items.length >= GAME_HISTORY_PAGE_SIZE ||
query.isFetching ||
query.isLoading
) {
return
}
lastRevealedRoundRef.current = revealRoundId
void query.refetch()
}, [
authStatus,
items.length,
query.isFetching,
query.isLoading,
query.refetch,
roundId,
winningCellId,
revealPhase,
revealRoundId,
])
return {

View File

@@ -492,6 +492,8 @@ function applyPeriodOpenedMessage(
message: GameSocketMessage,
serverTime: number | null,
) {
console.log('%c[period.opened 开奖数据]', 'color: red;', message)
applyPeriodMessage(message, serverTime)
const period = extractPeriodEventData(message)
@@ -580,6 +582,8 @@ function applyWalletChangedMessage(message: GameSocketMessage) {
}
function applyJackpotHitMessage(message: GameSocketMessage) {
console.log('%c[jackpot.hit 数据]', 'color: red;', message)
const jackpotHitData = extractJackpotHitData(message)
if (jackpotHitData?.hits.length) {