feat(game): 更新游戏页面功能和认证刷新机制

- 将开发环境代理目标从 192.168.1.5 改为 127.0.0.1
- 重构 auth.ts 文件中的代码缩进格式
- 实现自动令牌刷新机制,支持 JWT 过期时间检测
- 添加 WebSocket 连接的令牌强制刷新逻辑
- 新增 WindSquare 组件显示方位风向图标
- 实现动态座位风向计算和显示功能
- 优化 WebSocket URL 构建方式,移除查询参数中的令牌传递
- 添加登录失效时自动跳转到登录页面的功能
- 限制玩家名称显示长度为4个字符
- 改进 WebSocket 错误处理和重连机制
This commit is contained in:
2026-03-25 22:11:54 +08:00
parent 43744c2203
commit 0f1684b8d7
14 changed files with 480 additions and 370 deletions

View File

@@ -0,0 +1,151 @@
<script setup lang="ts">
import triangleIcon from '../../assets/images/icons/triangle.svg'
defineProps<{
seatWinds: {
top: string
right: string
bottom: string
left: string
}
}>()
</script>
<template>
<div class="wind-square">
<img class="triangle top" :src="triangleIcon" alt="" />
<img class="triangle right" :src="triangleIcon" alt="" />
<img class="triangle bottom" :src="triangleIcon" alt="" />
<img class="triangle left" :src="triangleIcon" alt="" />
<span class="wind-slot wind-top">
<img class="wind-icon" :src="seatWinds.top" alt="北位风" />
</span>
<span class="wind-slot wind-right">
<img class="wind-icon" :src="seatWinds.right" alt="右位风" />
</span>
<span class="wind-slot wind-bottom">
<img class="wind-icon" :src="seatWinds.bottom" alt="本位风" />
</span>
<span class="wind-slot wind-left">
<img class="wind-icon" :src="seatWinds.left" alt="左位风" />
</span>
</div>
</template>
<style scoped>
.wind-square {
position: relative;
width: 128px;
height: 128px;
border-radius: 18px;
}
.wind-square::before {
content: '';
position: absolute;
inset: 18px;
border-radius: 10px;
background:
radial-gradient(circle at 50% 45%, rgba(244, 222, 151, 0.2), rgba(12, 40, 30, 0.05) 65%),
linear-gradient(145deg, rgba(21, 82, 58, 0.42), rgba(8, 38, 27, 0.16));
box-shadow:
inset 0 0 0 1px rgba(255, 225, 165, 0.15),
0 6px 12px rgba(0, 0, 0, 0.24);
}
.triangle {
position: absolute;
width: 64px;
height: 64px;
object-fit: contain;
opacity: 0.96;
filter: drop-shadow(0 3px 6px rgba(0, 0, 0, 0.3));
}
.triangle.top {
top: 4px;
left: 32px;
transform: rotate(0deg);
filter:
hue-rotate(-8deg)
saturate(1.35)
brightness(1.1)
drop-shadow(0 3px 6px rgba(0, 0, 0, 0.3));
}
.triangle.right {
top: 32px;
right: 4px;
transform: rotate(90deg);
filter:
hue-rotate(16deg)
saturate(1.28)
brightness(1.08)
drop-shadow(0 3px 6px rgba(0, 0, 0, 0.3));
}
.triangle.bottom {
bottom: 4px;
left: 32px;
transform: rotate(180deg);
filter:
hue-rotate(34deg)
saturate(1.2)
brightness(1.02)
drop-shadow(0 3px 6px rgba(0, 0, 0, 0.3));
}
.triangle.left {
top: 32px;
left: 4px;
transform: rotate(270deg);
filter:
hue-rotate(-26deg)
saturate(1.24)
brightness(1.06)
drop-shadow(0 3px 6px rgba(0, 0, 0, 0.3));
}
.wind-slot {
position: absolute;
width: 32px;
height: 32px;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 9px;
background:
linear-gradient(180deg, rgba(255, 237, 186, 0.92), rgba(232, 191, 105, 0.84));
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.56),
0 3px 8px rgba(0, 0, 0, 0.26);
}
.wind-icon {
width: 24px;
height: 24px;
object-fit: contain;
filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.2));
}
.wind-top {
top: 12px;
left: 48px;
}
.wind-right {
top: 48px;
right: 12px;
}
.wind-bottom {
bottom: 12px;
left: 48px;
}
.wind-left {
top: 48px;
left: 12px;
}
</style>