Commit 740e86b2 authored by 陈冲's avatar 陈冲

feat: 后端接口优化

parent aebc5dc7
......@@ -34,8 +34,6 @@ const GAME_RUNNING_SECS: u64 = 60;
struct RoomPlayer {
/// 成绩分数,具体含义由前端和游戏逻辑自行定义,后端只负责存储和排序。
score: i64,
/// 客户端上一次提交的累计分数,用于重连后继续累计而不是覆盖旧分数。
last_client_score: i64,
// /// wechat原始token用于记录
// wechat: String,
/// 是否在线,离线的玩家不允许提交分数,但保留在排行榜里。
......@@ -474,6 +472,7 @@ async fn handle_room_command(
}
}
state.reset();
state.current_game_id = Some(format!("game{index}"));
state.status = RoomStatus::Start;
// let snapshot = state.snapshot();
drop(state);
......@@ -493,8 +492,14 @@ async fn handle_room_command(
//超过300人的情况
if get_player_count() > 300 {
emit_msgpack(&socket, evt, &err_resp("本场游戏人员已满", Some(json!(3))));
_ = socket.clone().disconnect();
return;
}
let gameId = data
.get("gameId")
.and_then(|v| v.as_str())
.unwrap_or("")
.to_string();
let nickname = data
.get("nickname")
.and_then(|value| value.as_str())
......@@ -507,6 +512,22 @@ async fn handle_room_command(
.to_string();
if let Ok(mut state) = ROOM_STATE.lock() {
let Some(current_game_id) = state.current_game_id.clone() else {
drop(state);
return;
};
// 当前h5进入的不是大屏开启的游戏房间
if current_game_id != gameId {
drop(state);
emit_msgpack(
&socket,
evt,
&err_resp("当前游戏房间还未开启", Some(json!(2))),
);
_ = socket.clone().disconnect();
return;
}
let already_joined = state.players.contains_key(userid);
if already_joined {
if let Some(player) = state.players.get_mut(userid) {
......@@ -532,7 +553,11 @@ async fn handle_room_command(
.and_then(|payload| payload.get("gameId"))
.and_then(|value| value.as_str())
{
emit_msgpack(&socket, "game_start_result", &ok_resp(Some(json!(game_id))));
emit_msgpack(
&socket,
"game_start_result",
&ok_resp(Some(json!(game_id))),
);
}
}
return;
......@@ -547,6 +572,7 @@ async fn handle_room_command(
Some(json!(2)),
),
);
_ = socket.clone().disconnect();
return;
}
let entry_order = state.next_entry_order;
......@@ -562,7 +588,6 @@ async fn handle_room_command(
})
.or_insert(RoomPlayer {
score: 0,
last_client_score: 0,
online: true,
entry_order,
nickname: nickname.to_string(),
......@@ -576,7 +601,7 @@ async fn handle_room_command(
if let Some(mut player) = CLIENT_PLAYER_MAP.get_mut(userid) {
player.0 = 1;
}
emit_msgpack(&socket, evt, &ok_resp(None));
emit_msgpack(&socket, evt, &ok_resp(Some(json!(current_game_id))));
// 给所有管理员广播房间状态更新
broadcast_msgpack_all_admin(
evt,
......@@ -630,9 +655,12 @@ async fn handle_room_command(
if !state.players.contains_key(userid) {
drop(state);
emit_msgpack(&socket, evt, &err_resp("您不在房间中", None));
_ = socket.clone().disconnect();
return;
} else if !matches!(state.status, RoomStatus::Running) {
drop(state);
emit_msgpack(&socket, evt, &err_resp("游戏还未开始", None));
return;
}
/* else if !state
.players
......@@ -645,16 +673,11 @@ async fn handle_room_command(
}*/
else if state.players.contains_key(userid) {
let player = state.players.get_mut(userid).unwrap();
let score_delta = if score >= player.last_client_score {
score - player.last_client_score
} else {
score
};
player.score += score_delta.max(0);
player.last_client_score = score;
player.score = score;
// player.wechat = wechat.to_string();
player.online = true;
drop(state);
return;
// 方案1:每有一名玩家提交时发送给所有玩家跟管理员,玩家过多时发送太频繁,
// 这里会选第2种方案, 游戏中时每秒发给所有玩家跟管理员 (push_room_score_ranking)
......@@ -667,6 +690,7 @@ async fn handle_room_command(
} else {
drop(state);
emit_msgpack(&socket, evt, &err_resp("提交异常", None));
return;
}
}
}
......@@ -683,25 +707,34 @@ async fn handle_room_command(
if wechat.is_empty() {
return;
}
let (score, rank) = if let Ok(state) = ROOM_STATE.lock() {
let (score, rank, ranking) = if let Ok(state) = ROOM_STATE.lock() {
//防止客户端提交的状态还在Running中
if !matches!(state.status, RoomStatus::Submit | RoomStatus::Running) {
drop(state);
return;
}
let full_ranking = state.full_score_ranking();
let ranking = RoomState::ranking_payload(
&full_ranking
.iter()
.take(ROOM_SCORE_RANK_LIMIT)
.cloned()
.collect::<Vec<_>>(),
);
let server_score = state
.players
.get(userid)
.map(|player| player.score)
.unwrap_or(score);
let server_rank = state
.player_rank(userid)
.map(|rank| rank as i64)
let server_rank = full_ranking
.iter()
.position(|player| player.wechat == userid)
.map(|index| (index + 1) as i64)
.unwrap_or(rank);
drop(state);
(server_score, server_rank)
(server_score, server_rank, ranking)
} else {
(score, rank)
(score, rank, Vec::new())
};
let game = Game {
wechat_id: wechat.to_string(),
......@@ -713,7 +746,14 @@ async fn handle_room_command(
create_date: None,
};
if game.insert().await {
emit_msgpack(&socket, evt, &ok_resp(None));
emit_msgpack(
&socket,
evt,
&ok_resp(Some(json!({
"list": ranking,
"rank": rank
}))),
);
} else {
emit_msgpack(&socket, evt, &err_resp("提交异常", None));
}
......@@ -926,7 +966,6 @@ pub async fn login(req: &mut Request, res: &mut Response) {
let params = match req.parse_body::<HashMap<String, String>>().await {
Ok(params) => params,
Err(_) => {
res.status_code(StatusCode::BAD_REQUEST);
res.render(Json(err_resp("参数格式错误", None)));
return;
}
......@@ -942,7 +981,6 @@ pub async fn login(req: &mut Request, res: &mut Response) {
.unwrap_or_default();
if username.is_empty() || password.is_empty() {
res.status_code(StatusCode::BAD_REQUEST);
res.render(Json(err_resp("username 和 password 不能为空", None)));
return;
}
......@@ -963,9 +1001,15 @@ pub async fn login(req: &mut Request, res: &mut Response) {
let passphrase = utils::get_aes_passphrase();
if passphrase.is_none() {
res.status_code(StatusCode::BAD_REQUEST);
res.render(Json(err_resp("username 和 password 不能为空", None)));
return;
}
//当前管理员已登录,不能重复登录
if (CLIENT_ADMIN_MAP.contains_key(&manager.token)) {
res.render(Json(err_resp("当前管理员已登录,不能重复登录", None)));
return;
}
res.render(Json(ok_resp(Some(json!({
"passphrase": passphrase,
"token": manager.token,
......
......@@ -12,12 +12,14 @@
"crypto-js": "^4.2.0",
"msgpack": "^1.0.3",
"socket.io-client": "^4.8.3",
"vconsole": "^3.15.1",
"vue": "^3.5.32",
"vue-router": "^4.6.4"
},
"devDependencies": {
"@tsconfig/node24": "^24.0.4",
"@types/node": "^24.12.2",
"@vitejs/plugin-basic-ssl": "^2.3.0",
"@vitejs/plugin-vue": "^6.0.6",
"@vue/tsconfig": "^0.9.1",
"npm-run-all2": "^8.0.4",
......@@ -438,6 +440,15 @@
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@babel/runtime": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz",
"integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/template": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz",
......@@ -929,6 +940,19 @@
"undici-types": "~7.16.0"
}
},
"node_modules/@vitejs/plugin-basic-ssl": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-2.3.0.tgz",
"integrity": "sha512-bdyo8rB3NnQbikdMpHaML9Z1OZPBu6fFOBo+OtxsBlvMJtysWskmBcnbIDhUqgC8tcxNv/a+BcV5U+2nQMm1OQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^18.0.0 || ^20.0.0 || >=22.0.0"
},
"peerDependencies": {
"vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
"node_modules/@vitejs/plugin-vue": {
"version": "6.0.7",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.7.tgz",
......@@ -1334,6 +1358,29 @@
"dev": true,
"license": "MIT"
},
"node_modules/copy-text-to-clipboard": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.2.tgz",
"integrity": "sha512-T6SqyLd1iLuqPA90J5N4cTalrtovCySh58iiZDGJ6FGznbclKh4UI+FGacQSgFzwKG77W7XT5gwbVEbd9cIH1A==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/core-js": {
"version": "3.49.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.49.0.tgz",
"integrity": "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==",
"hasInstallScript": true,
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/core-js"
}
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
......@@ -2035,6 +2082,11 @@
"dev": true,
"license": "MIT"
},
"node_modules/mutation-observer": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/mutation-observer/-/mutation-observer-1.0.3.tgz",
"integrity": "sha512-M/O/4rF2h776hV7qGMZUH3utZLO/jK7p8rnNgGkjKUw8zCGjRQPxB8z6+5l8+VjRUQ3dNYu4vjqXYLr+U8ZVNA=="
},
"node_modules/nan": {
"version": "2.27.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.27.0.tgz",
......@@ -2512,6 +2564,18 @@
"browserslist": ">= 4.21.0"
}
},
"node_modules/vconsole": {
"version": "3.15.1",
"resolved": "https://registry.npmjs.org/vconsole/-/vconsole-3.15.1.tgz",
"integrity": "sha512-KH8XLdrq9T5YHJO/ixrjivHfmF2PC2CdVoK6RWZB4yftMykYIaXY1mxZYAic70vADM54kpMQF+dYmvl5NRNy1g==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.17.2",
"copy-text-to-clipboard": "^3.0.1",
"core-js": "^3.11.0",
"mutation-observer": "^1.0.3"
}
},
"node_modules/vite": {
"version": "8.0.14",
"resolved": "https://registry.npmjs.org/vite/-/vite-8.0.14.tgz",
......
......@@ -8,13 +8,15 @@ const props = withDefaults(defineProps<{
mode?: 'contain' | 'cover'
backgroundMode?: 'contain' | 'cover',
showGameRule?: boolean,
showGameRank?: boolean,
}>(), {
background: 'linear-gradient(180deg, #fbf7ef 0%, #ffe7dc 100%)',
width: 750,
height: 1624,
mode: 'contain',
backgroundMode: 'cover',
showGameRule: false
showGameRule: false,
showGameRank: false
})
const emit = defineEmits<{
......@@ -156,6 +158,11 @@ defineExpose({
<slot name="gameRule"></slot>
</div>
</Transition>
<Transition name="game-rule-fade">
<div v-if="!countdownVisible && showGameRank" class="modal-container">
<slot name="gameRank"></slot>
</div>
</Transition>
</main>
</template>
......
......@@ -22,6 +22,8 @@ type GameSocketOptions = {
onRoomBack?: (data: any) => void
}
let gameId = '';
function getGameIndex(data: any) {
if (typeof data === 'object' && data !== null) {
return Number(data.game ?? data.game_id ?? data.gameId ?? data.id)
......@@ -41,7 +43,7 @@ function getGameHomePath(data: any) {
}
export function joinSharedRoom(nickname: string, token: string, avatar: string) {
return sendSocketMessage('room_join', { nickname: nickname, token, avatar })
return sendSocketMessage('room_join', { nickname: nickname, token, avatar, gameId: gameId })
}
export function sendGameMessage(cmd: string, data: any = {}) {
......@@ -50,6 +52,7 @@ export function sendGameMessage(cmd: string, data: any = {}) {
export const userJoinStatus = ref(false)
export function useGameSocket(options: GameSocketOptions) {
gameId = options.gameId;
const router = useRouter()
let socket: Socket | null = null
let offSocketMessage: (() => void) | undefined
......@@ -76,7 +79,10 @@ export function useGameSocket(options: GameSocketOptions) {
if (evt === 'room_join_result') {
switch (data) {
case 1: userJoinStatus.value = true; break;
case 3: alert(msg); break;
case 2:
case 3:
alert(msg);
break;
}
} else if (evt == 'submit_score_save') {
//提交分数的情况下有问题的情况下,只重试3次
......@@ -106,6 +112,10 @@ export function useGameSocket(options: GameSocketOptions) {
break
}
case 'room_join_result': {
if (data != options.gameId) {
alert('当前游戏房间还未开启');
return;
}
userJoinStatus.value = true
break
}
......
<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref } from 'vue'
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
import { cssAssetUrl } from '@/commons/assets.ts'
import MobileStage from '@/components/MobileStage.vue'
import { useGameSocket, joinSharedRoom, sendGameMessage, userJoinStatus } from '@/composables/useGameSocket'
import LoadingView from './views/LoadingView.vue'
import PlayingView from './views/PlayingView.vue'
import ScoreView from './views/ScoreView.vue'
import { $getWechat } from '@/commons/utils.ts'
import { playGame1Music } from '@/commons/music'
type GameView = 'loading' | 'playing' | 'score'
type GameView = 'loading' | 'playing'
type RankPlayer = {
rank: number
nickname: string
avatar: string
score: number | string
}
const imageUrls: Record<string, string> = {
bg: cssAssetUrl('game6/bg.png'),
......@@ -29,6 +34,8 @@ const imageUrls: Record<string, string> = {
rabbitshowprite: cssAssetUrl('game6/rabbit_show.png'),
land: cssAssetUrl('game6/land.png'),
hammer: cssAssetUrl('game6/hammer.png'),
ranklist: cssAssetUrl('game6/ranklist.png'),
rule: cssAssetUrl('game1/rule.png')
}
const wechat = $getWechat()
......@@ -37,6 +44,19 @@ const countdownInterval = ref(60)
const isDivDescVisible = ref(false)
const score = ref(0)
const rank = ref(0) //排名
const rankList = ref<RankPlayer[]>([])
const displayRankList = computed<RankPlayer[]>(() => {
const list = rankList.value.slice(0, 10)
return Array.from({ length: 10 }, (_, index) => {
return list[index] ?? {
rank: index + 1,
nickname: '-',
avatar: '',
score: '-',
}
})
})
// const guFrames: [string, string, string] = [imageUrls.gu01, imageUrls.gu02, imageUrls.gu03]
// const currentGu = ref(imageUrls.gu01)
const isGuPlaying = ref(false)
......@@ -44,6 +64,7 @@ const token = ref(wechat?.token ?? '')
const nickname = ref(wechat?.nickname ?? '')
const avatar = ref(wechat?.avatar ?? '')
const showGameRule = ref(false)
const showGameRank = ref(false)
const mobileStageRef = ref<InstanceType<typeof MobileStage> | null>(null)
const _offSocketMessage = ref<(() => void) | undefined>()
......@@ -66,21 +87,21 @@ function stopGameCountdown() {
}
}
function submitScore(save: boolean = false) {
function submitScore(save: boolean = false, currentTick = score.value) {
//最后提交保存在数据库中
if (save) {
//item_num 游戏项目(1到6)
//wechat 原始token
sendGameMessage('submit_score_save', {
score: score.value,
score: currentTick,
wechat: wechat.token_origin,
item_num: 1,
item_num: 6,
nickname: wechat.nickname,
avatar: wechat.avatar,
rank: rank.value,
})
} else {
sendGameMessage('submit_score', { score: score.value })
sendGameMessage('submit_score', { score: currentTick })
}
}
......@@ -97,7 +118,7 @@ function startGameCountdown(seconds = 60) {
gameCountdownTimer = undefined
setDivDescVisible(false)
submitScore(true)
showScoreView()
showGameOverRank()
return
}
......@@ -121,10 +142,12 @@ function resetToLoadingView() {
}
score.value = 0
rank.value = 0
rankList.value = []
countdownInterval.value = 60
// currentGu.value = guFrames[0]
isGuPlaying.value = false
userJoinStatus.value = false
showGameRank.value = false
currentView.value = 'loading'
setDivDescVisible(false)
}
......@@ -132,24 +155,19 @@ function resetToLoadingView() {
function startGameView() {
stopGameCountdown()
score.value = 0
rank.value = 0
rankList.value = []
// currentGu.value = guFrames[0]
showGameRank.value = false
currentView.value = 'playing'
startGameCountdown()
}
function showScoreView() {
function showGameOverRank() {
stopGameCountdown()
setDivDescVisible(false)
currentView.value = 'score'
}
function replayGame() {
startGameView()
}
function backToWaiting() {
resetToLoadingView()
joinSharedRoom(nickname.value, token.value, avatar.value)
currentView.value = 'loading'
showGameRank.value = true
}
function handleRoomBack() {
......@@ -160,8 +178,9 @@ function handleRoomBack() {
}
const touchHandler = (scoreDelta: number) => {
score.value += scoreDelta
submitScore()
const nextTick = score.value + scoreDelta
score.value = nextTick
submitScore(false, nextTick)
playGame1Music();
}
......@@ -187,6 +206,20 @@ if (wechat) {
if (Number.isFinite(nextRank) && nextRank > 0) {
rank.value = nextRank
}
} else if (typeof data === 'object' && data) {
if (Array.isArray(data.list)) {
rankList.value = data.list.map((item: any, index: number) => ({
rank: Number(item?.rank ?? index + 1),
nickname: String(item?.nickname ?? ''),
avatar: String(item?.avatar ?? ''),
score: Number(item?.score ?? 0),
}))
}
const nextRank = Number(data.rank)
if (Number.isFinite(nextRank) && nextRank > 0) {
rank.value = nextRank
}
}
},
onRescoreSubmitted: (_recount) => {
......@@ -221,34 +254,73 @@ const showGameRuleHandler = () => {
}
const renderBG = () => {
if (currentView.value === 'loading') {
return `${imageUrls.bg} center/cover`;
if (currentView.value == 'playing') {
return `${imageUrls.bg2} center/cover`
}
return `${imageUrls.bg2} center/cover`
return `${imageUrls.bg} center/cover`;
}
const rankCloseHandler = () => {
showGameRank.value = false
}
</script>
<template>
<MobileStage v-if="token" :showGameRule="showGameRule" ref="mobileStageRef" :background="`${renderBG()}`">
<MobileStage v-if="token" :showGameRule="showGameRule" :showGameRank="showGameRank" ref="mobileStageRef"
:background="`${renderBG()}`">
<template #gameRule>
<div class="rule-container">
<div class="rule-txt-container">
<div class="rule-title">游戏规则</div>
<div class="rule-txt">
微信用户通过扫描大屏幕二维码参与,可容纳多人同时进行且比拼打地鼠,谁打的最多即为获胜,游戏结束按分值高低先后排名,有机会获得新疆福彩定制周边礼品一份。
1. 主持人开赛点击敲击,打中地鼠 + 5 分、误击白兔-3分;<br />
2. 限时比拼反应速度,结束后按积分排名;<br />
3. 高分用户有机会领取新疆福彩定制周边;<br />
4. 禁止外挂作弊,违规账号取消成绩与领奖资格;<br /><br />
祝您游戏愉快!
</div>
</div>
<div class="rule-close">
<div @click="showGameRuleHandler"></div>
<div class="rule-close" @click="showGameRuleHandler"></div>
</div>
</template>
<template #gameRank>
<div class="ranklist-container">
<div class="txt-title">排行</div>
<div class="list-container">
<div class="row row-1">
<div class="col-1">排名</div>
<div class="col-2">用户</div>
<div class="col-3">成绩</div>
</div>
<div class="row-2">
<div class="row rank-row" v-for="(item, index) in displayRankList"
:key="`${item.rank}-${index}`">
<div class="col-1">
<div>{{ item.rank }}</div>
</div>
<div class="col-2">
<div class="avatar"
:style="item.avatar ? { backgroundImage: `url(${item.avatar})` } : {}"></div>
<div>{{ item.nickname }}</div>
</div>
<div class="col-3">{{ item.score }}</div>
</div>
</div>
<div class="row row-3">
<div class="col-1">{{ rank > 0 ? rank : '未上榜' }}</div>
<div class="col-2">
<div class="avatar" :style="{ backgroundImage: `url(${avatar})` }"></div>
<div>{{ nickname }}</div>
</div>
<div class="col-3">{{ score }}</div>
</div>
</div>
</div>
<div class="img-close" @click="rankCloseHandler"></div>
</template>
<LoadingView v-if="currentView === 'loading'" :image-urls="imageUrls" :user-join-status="userJoinStatus"
@touchGameRule="showGameRuleHandler" />
<PlayingView v-else-if="currentView === 'playing'" :image-urls="imageUrls" :tick="score" :rank="rank"
:countdown-interval="countdownInterval" :is-div-desc-visible="isDivDescVisible" @touch="touchHandler" />
<ScoreView v-else :image-urls="imageUrls" :rank="rank" :tick="score" @replay="replayGame"
@back="backToWaiting" />
<PlayingView v-else :image-urls="imageUrls" :tick="score" :rank="rank" :countdown-interval="countdownInterval"
:is-div-desc-visible="isDivDescVisible" @touch="touchHandler" />
</MobileStage>
<div v-else style="text-align: center; width: 100vw; height: 100vh; line-height: 30; font-size: 20px;">
请使用微信扫码进入游戏
......@@ -257,41 +329,130 @@ const renderBG = () => {
<style scoped>
.rule-container {
.rule-txt-container {
background: #FFF9E4;
margin: 0 40px;
border-radius: 5px;
padding-top: 20px;
padding-bottom: 10px;
position: absolute;
background: v-bind('imageUrls.rule') center / cover no-repeat;
width: 692px;
height: 797px;
left: -157px;
top: -75px;
transform: scale(0.5);
.rule-title {
text-align: center;
color: #850000;
color: white;
font-weight: bold;
font-size: 15pt;
font-size: 22pt;
margin-top: 10px;
letter-spacing: 4px;
}
.rule-txt {
font-size: 12pt;
padding: 10px;
font-size: 26pt;
padding: 40px;
margin-top: 10px;
color: #AA0000;
}
}
.rule-close {
width: 32px;
height: 130px;
width: 57px;
height: 57px;
margin: 0 auto;
margin-top: 450px;
background: v-bind('imageUrls.close') center/cover;
position: relative;
transform: scale(0.8);
}
}
.ranklist-container {
width: 747px;
height: 1084px;
background: v-bind('imageUrls.ranklist');
transform: translate(-50%, -50%) scale(0.45);
left: 50%;
top: 50%;
position: absolute;
.txt-title {
width: 100%;
text-align: center;
font-size: 50px;
margin-top: 35px;
font-weight: bold;
color: #AA0000;
letter-spacing: 2px;
}
.list-container {
width: calc(100% - 90px);
height: calc(100% - 210px);
position: absolute;
left: 40px;
top: 140px;
text-align: center;
height: 73px;
line-height: 73px;
font-size: 32px;
.row {
display: grid;
grid-template-columns: 150px auto 150px;
align-items: center;
}
>div {
position: absolute;
bottom: 0;
width: 32px;
height: 32px;
border-radius: 16px;
.row-1 {
color: #AA0000;
font-weight: bold;
background: linear-gradient(-84deg, #FFD396 0%, #FFF3D1 53%, #FFD59C 100%);
border-radius: 20px 20px 0px 0px;
}
.row-2 {
color: #633911;
.rank-row:nth-child(odd) {
background: #F2E2AE;
}
.rank-row:nth-child(even) {
background: #FCEEBF;
}
.col-1 {
position: relative;
}
}
.row-3 {
background: linear-gradient(0deg, #F4B64C 0%, #F7C96F 100%);
border-radius: 0px 0px 20px 20px;
}
.col-2 {
display: flex;
align-items: center;
justify-content: center;
gap: 18px;
.avatar {
width: 48px;
height: 48px;
flex: 0 0 auto;
border-radius: 50%;
background-position: center;
background-size: cover;
}
}
}
}
.img-close {
width: 57px;
height: 57px;
border-radius: 29px;
background: v-bind('imageUrls.close')center/cover;
transform: scale(0.7);
margin-top: 500px;
}
</style>
......@@ -28,6 +28,7 @@ type TargetItem = {
}
const list = ref<TargetItem[]>([]);
const moleContainerRef = ref<HTMLElement | null>(null)
for (let i = 0; i < 9; i++) {
list.value.push({
id: i,
......@@ -129,6 +130,45 @@ function handleTargetTouch(index: number) {
}, item.hitMs)
}
function handleBoardTouch(event: MouseEvent) {
const container = moleContainerRef.value
if (!container) {
return
}
const rect = container.getBoundingClientRect()
const x = ((event.clientX - rect.left) / rect.width) * 750
const y = ((event.clientY - rect.top) / rect.height) * 600
const colWidth = 250
const rowGap = 70
const rowHeight = (600 - rowGap * 2) / 3
const hitRadius = 225
let targetIndex = -1
let targetDistance = Number.POSITIVE_INFINITY
list.value.forEach((item, index) => {
if (!item.kind || item.state === 'idle' || item.state === 'hit') {
return
}
const col = index % 3
const row = Math.floor(index / 3)
const centerX = col * colWidth + colWidth / 2
const centerY = row * (rowHeight + rowGap) + rowHeight / 2
const distance = Math.hypot(x - centerX, y - centerY)
if (distance <= hitRadius && distance < targetDistance) {
targetIndex = index
targetDistance = distance
}
})
if (targetIndex >= 0) {
handleTargetTouch(targetIndex)
}
}
onMounted(() => {
scheduleRandomTargets()
})
......@@ -165,16 +205,14 @@ onBeforeUnmount(() => {
</div>
</div>
<div class="mole-container">
<div ref="moleContainerRef" class="mole-container" @click="handleBoardTouch">
<div v-for="(item, index) in list" :key="item.id">
<div class="img-land"></div>
<button v-if="item.kind" class="mole-hit-area" type="button" @click="handleTargetTouch(index)">
<span class="img-mole" :class="[`is-${item.kind}`, `is-${item.state}`]" :style="{
<span v-if="item.kind" class="img-mole" :class="[`is-${item.kind}`, `is-${item.state}`]" :style="{
'--show-duration': `${item.showMs}ms`,
'--hide-duration': `${item.hideMs}ms`,
'--hit-duration': `${item.hitMs}ms`,
}"></span>
</button>
'--hit-duration': `${item.hitMs}ms`,
}"></span>
</div>
</div>
<div class="img-hammer"></div>
......@@ -266,18 +304,6 @@ onBeforeUnmount(() => {
}
}
.mole-hit-area {
position: absolute;
inset: 0;
}
.mole-hit-area {
z-index: 2;
padding: 0;
border: 0;
background: transparent;
}
.img-land,
.img-mole {
position: absolute;
......
......@@ -9,6 +9,7 @@ defineProps<{
}>()
defineEmits<{
showRank: []
replay: []
back: []
}>()
......@@ -24,23 +25,6 @@ onMounted(() => {
<template>
<div class="h5-page game-stage">
<div class="img-logo"></div>
<div class="bg-bottom"></div>
<!-- <div class="img-score">
<div class="score-avatar"
:style="`background: url(${avatar});border-radius:66px;width:132px;height:132px;`"></div>
<div class="score-content">
<div>{{ nickname }}</div>
<div>您的成绩</div>
<div>击鼓次数(次)</div>
<div>{{ tick }}</div>
<div>最终排名</div>
<div><label>{{ rank }}</label></div>
</div>
</div>
<div class="btn-group">
<div class="btn-replay" @click="$emit('replay')"></div>
<div class="btn-back" @click="$emit('back')"></div>
</div> -->
</div>
</template>
......@@ -52,16 +36,6 @@ onMounted(() => {
padding: 0;
}
.bg-bottom {
position: absolute;
bottom: 0;
left: var(--stage-viewport-left, 0);
width: var(--stage-viewport-width, 750px);
height: 479px;
background: v-bind('imageUrls.bg') center/cover;
opacity: 0.6;
}
.img-logo {
position: absolute;
top: 66px;
......
......@@ -10,7 +10,6 @@
"dependencies": {
"@msgpack/msgpack": "^3.1.3",
"crypto-js": "^4.2.0",
"msgpack": "^1.0.3",
"socket.io-client": "^4.8.3",
"vue": "^3.5.32",
"vue-router": "^4.6.4"
......@@ -597,9 +596,9 @@
}
},
"node_modules/@oxc-project/types": {
"version": "0.132.0",
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.132.0.tgz",
"integrity": "sha512-FESMOxil5Se014ui/Eq8fT5uHJo6nIRwH0PfJrZJXs6Gek3ZVFOrpUv3YIZT20m+extU98Hg1Ym72U58rlsxUQ==",
"version": "0.133.0",
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.133.0.tgz",
"integrity": "sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==",
"dev": true,
"license": "MIT",
"funding": {
......@@ -614,9 +613,9 @@
"license": "MIT"
},
"node_modules/@rolldown/binding-android-arm64": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.2.tgz",
"integrity": "sha512-ZS4D1JPGn/MYQN/SYDWftIE/nVsM8j/AFOYEzAoOE2O3NktQOZru+/vYXGbR/qtdLdIfGCP0lcoJiYVzsEz+iQ==",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.3.tgz",
"integrity": "sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==",
"cpu": [
"arm64"
],
......@@ -631,9 +630,9 @@
}
},
"node_modules/@rolldown/binding-darwin-arm64": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.2.tgz",
"integrity": "sha512-vdFA9+C/rekyGce7WqHs/xoT0ioZEWaOFyZLIV1mEeNFaFDUQrPIo8Vs2GvJ6eetb3rzDUtUBgzto3ExpXJB3w==",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.3.tgz",
"integrity": "sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==",
"cpu": [
"arm64"
],
......@@ -648,9 +647,9 @@
}
},
"node_modules/@rolldown/binding-darwin-x64": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.2.tgz",
"integrity": "sha512-BewSOwTHazv77DTYiAZXSqqKZ4KP/KonFisDMVU7PImxoWfB2aepnPhd2E4SWz3zDzYgDNbs6jBmTdgNnF02GA==",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.3.tgz",
"integrity": "sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==",
"cpu": [
"x64"
],
......@@ -665,9 +664,9 @@
}
},
"node_modules/@rolldown/binding-freebsd-x64": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.2.tgz",
"integrity": "sha512-m41o7M0YWtUdqk61Tb+jnKb2rN++iRdIASlExkUoKfIAH30DOHCB8fVLzSUpbWHHU8esmEioY62PxzexE8MBuA==",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.3.tgz",
"integrity": "sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==",
"cpu": [
"x64"
],
......@@ -682,9 +681,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm-gnueabihf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.2.tgz",
"integrity": "sha512-jcojB9H7W/jS29pMKWAK1N+fU99vXodHDTatS3b3y/XSOCiHo0kkA74pL3jJmkoQtYpOCxDvaKs1fo2Ij/1X5w==",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.3.tgz",
"integrity": "sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==",
"cpu": [
"arm"
],
......@@ -699,9 +698,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm64-gnu": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.2.tgz",
"integrity": "sha512-1jn6qDU5iiOgFgygDzKUuKP0maTi0/f1+sBLgvij/76C77Nm3ts6ufz9Bjg5q5dduxiUIxtq86JIoBvo1xQ4Ig==",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.3.tgz",
"integrity": "sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==",
"cpu": [
"arm64"
],
......@@ -719,9 +718,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm64-musl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.2.tgz",
"integrity": "sha512-QVLO/czFMdoMFSqlX3bcswcJNm/23r+qoa/jgtmFc/qEp6/jXmIkDjF/XIo8dPfGaiwy1xfQn8o77L79GeXFgw==",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.3.tgz",
"integrity": "sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==",
"cpu": [
"arm64"
],
......@@ -739,9 +738,9 @@
}
},
"node_modules/@rolldown/binding-linux-ppc64-gnu": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.2.tgz",
"integrity": "sha512-hgO5Abm0w5UL6FEa2iFnZqo2KlK7TQ5QhV5x09hujBf7t5KzHQ1VmfPuTpqRy/rNlSxua3eWH374xxiVrP+lcA==",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.3.tgz",
"integrity": "sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==",
"cpu": [
"ppc64"
],
......@@ -759,9 +758,9 @@
}
},
"node_modules/@rolldown/binding-linux-s390x-gnu": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.2.tgz",
"integrity": "sha512-fy8rXxuYEu602abC8MUNaPjYLIFzReOaEIEMKMUa0rFEUxNpVXhs15KSSQ4qlqSaM7B6rcj9rDZgADh/IGDzLQ==",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.3.tgz",
"integrity": "sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==",
"cpu": [
"s390x"
],
......@@ -779,9 +778,9 @@
}
},
"node_modules/@rolldown/binding-linux-x64-gnu": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.2.tgz",
"integrity": "sha512-0+bOkiQ779+r1WpoHOWHqncvyySci0vKph+myNDYb+im6meJAzHQXay6oEgnkHuUGouM1LKTZwqKpBow6Kj7CQ==",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.3.tgz",
"integrity": "sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==",
"cpu": [
"x64"
],
......@@ -799,9 +798,9 @@
}
},
"node_modules/@rolldown/binding-linux-x64-musl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.2.tgz",
"integrity": "sha512-mjSkrzZK5Qsl0a9d1JgILOiuZOSDTVdKENcSXBoqbzSrspLR/4/IRVDo5wd2GgZjNss/viBFJdeq+j7qH2nypw==",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.3.tgz",
"integrity": "sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==",
"cpu": [
"x64"
],
......@@ -819,9 +818,9 @@
}
},
"node_modules/@rolldown/binding-openharmony-arm64": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.2.tgz",
"integrity": "sha512-1v5vHasdfQAZoEHakBV72LIFAC9JjnymsiKxp+GEr/ma3+NJCPSaYK+qavInOovJkgwFrs7GccX2d6IgDA3Z5w==",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.3.tgz",
"integrity": "sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==",
"cpu": [
"arm64"
],
......@@ -836,9 +835,9 @@
}
},
"node_modules/@rolldown/binding-wasm32-wasi": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.2.tgz",
"integrity": "sha512-mb1VobWn6NheziTk5/WEaR6AKVbrwT5sOi6C7zk3gy/pD1qtJfU1j4PgTo2NJnOtbL9Dl3Aeei8w9jJ7qC2jZQ==",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.3.tgz",
"integrity": "sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==",
"cpu": [
"wasm32"
],
......@@ -855,9 +854,9 @@
}
},
"node_modules/@rolldown/binding-win32-arm64-msvc": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.2.tgz",
"integrity": "sha512-SqKonF56vA/L2yHwHYcEp2P34URpOZ7d1fS635cTkpDnUtEGdUbhI6NzsPdqeSWvAAeGDrxjWjNmibDIdFf9/A==",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.3.tgz",
"integrity": "sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==",
"cpu": [
"arm64"
],
......@@ -872,9 +871,9 @@
}
},
"node_modules/@rolldown/binding-win32-x64-msvc": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.2.tgz",
"integrity": "sha512-v7qRI7gXLRINcOGXt+7YmAZ6iFuyZVMIoXAxhd8oP+DR9dLfL9GfNIx7PLMxmhZdvq8waUJBQiWN9EKNy+TRBQ==",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.3.tgz",
"integrity": "sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==",
"cpu": [
"x64"
],
......@@ -920,13 +919,13 @@
}
},
"node_modules/@types/node": {
"version": "24.12.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.4.tgz",
"integrity": "sha512-GUUEShf+PBCGW2KaXwcIt3Yk+e3pkKwWKb9GSyM9WQVE+ep2jzmHdGsHzu4wgcZy5fN9FBdVzjpBQsYlpfpgLA==",
"version": "24.13.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.0.tgz",
"integrity": "sha512-5vtOqGQr4NJKeEzV441FcOi2MeG9UTWq9LqVLGneDdu4vlX17H8kQ2PA2UmNwCUGPVDj4oBjNhS7ReVEIWJJrg==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~7.16.0"
"undici-types": "~7.18.0"
}
},
"node_modules/@vitejs/plugin-vue": {
......@@ -1029,53 +1028,53 @@
}
},
"node_modules/@vue/compiler-core": {
"version": "3.5.34",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.34.tgz",
"integrity": "sha512-s9cLyK5mLcvZ4Agva5QgRsQyLKvts9WbU9DB6NqiZkkGEdwmcEiylj5Jbwkp680drF/NNCV8OlAJSe+yMLxaJw==",
"version": "3.5.35",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.35.tgz",
"integrity": "sha512-BUmHaR1J+O+CKZ9uJucdVTEr1LHsdyvv7vG3eNRhK3CczEHeMd/LtsHAuD7PbrxvI2envCY2v7HI1vC1aBRzKw==",
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.29.3",
"@vue/shared": "3.5.34",
"@vue/shared": "3.5.35",
"entities": "^7.0.1",
"estree-walker": "^2.0.2",
"source-map-js": "^1.2.1"
}
},
"node_modules/@vue/compiler-dom": {
"version": "3.5.34",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.34.tgz",
"integrity": "sha512-EbF/T++k0e2MMZlJsBhzK8Sgwt0HcIPOhzn1CTB/lv6sQcyk+OWf8YeiLxZp3ro7MbbLcAfAJ6sEvjFWuNgUCw==",
"version": "3.5.35",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.35.tgz",
"integrity": "sha512-k+bprkXxuqhVajgTx5mUHuir7TwQzUKOWR40ng1ncAqQRPnrLngGGgqVEEhOnTMlc8btHYVKmrP8s5Qyg0hvYA==",
"license": "MIT",
"dependencies": {
"@vue/compiler-core": "3.5.34",
"@vue/shared": "3.5.34"
"@vue/compiler-core": "3.5.35",
"@vue/shared": "3.5.35"
}
},
"node_modules/@vue/compiler-sfc": {
"version": "3.5.34",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.34.tgz",
"integrity": "sha512-D/ihr6uZeIt6r+pVZf46RWT1fAsLFMbUP7k8G1VkiiWexriED9GrX3echHd4Abbt17zjlfiFJ8z7a3BxZOPNjg==",
"version": "3.5.35",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.35.tgz",
"integrity": "sha512-G5VPMcXTSywXBgtFOZOnHKBxKSrwXUcvY1iaF5/hRcy7t0J6CH/d8ha9F4nzi00Fax1eLV0QHM7v4mQu68jydw==",
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.29.3",
"@vue/compiler-core": "3.5.34",
"@vue/compiler-dom": "3.5.34",
"@vue/compiler-ssr": "3.5.34",
"@vue/shared": "3.5.34",
"@vue/compiler-core": "3.5.35",
"@vue/compiler-dom": "3.5.35",
"@vue/compiler-ssr": "3.5.35",
"@vue/shared": "3.5.35",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.21",
"postcss": "^8.5.14",
"postcss": "^8.5.15",
"source-map-js": "^1.2.1"
}
},
"node_modules/@vue/compiler-ssr": {
"version": "3.5.34",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.34.tgz",
"integrity": "sha512-cDtTHKibkThKGHH1SP+WdccquNRYQDFH6rRjQCqT9G2ltFAfoR5pUftpab/z+aM5mW9HLLVQW7hfKKQe/1GBeQ==",
"version": "3.5.35",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.35.tgz",
"integrity": "sha512-rGhAeXgdM7/ffTJGXT69rCCdTmjDewnFuUZfBQQHTdcEBeWdT5HCGY60y2ytLJr9/Dsu7IntUi5z/w0h6Rjnzw==",
"license": "MIT",
"dependencies": {
"@vue/compiler-dom": "3.5.34",
"@vue/shared": "3.5.34"
"@vue/compiler-dom": "3.5.35",
"@vue/shared": "3.5.35"
}
},
"node_modules/@vue/devtools-api": {
......@@ -1119,9 +1118,9 @@
"license": "MIT"
},
"node_modules/@vue/language-core": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-3.3.2.tgz",
"integrity": "sha512-CLwjSfHlPLhjd2qhuS3tTFtnOIWHXAM5u4X1DxmzlQ8j5bmOYlKCsSusOP7jCRJnlVg0mCTQtHU3vwFvopZGoQ==",
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-3.3.3.tgz",
"integrity": "sha512-X6p+7nfY7vVT6dQwUJ+v0Jfq/lwIfhL2jMi91dQ3ln4hnlGXlxsDu/FNkeyHYgvYtyQy18ZX76IZy7X4diDbiQ==",
"dev": true,
"license": "MIT",
"dependencies": {
......@@ -1135,53 +1134,53 @@
}
},
"node_modules/@vue/reactivity": {
"version": "3.5.34",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.34.tgz",
"integrity": "sha512-y9XDjCEuBp+98k+UL5dbYkh57AHU4o6cxZedOPXw3bmrZZYLQsVHguGurq7hVrPCSrQtrnz1f9dssyFr+dMXfQ==",
"version": "3.5.35",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.35.tgz",
"integrity": "sha512-tVc+SsHConvh/Lz64qq1pP3rYArBmK42xonovEcxY74SQtvctZodG/zhq54P5dr38cVuw25d27cPNRdlMidpGQ==",
"license": "MIT",
"dependencies": {
"@vue/shared": "3.5.34"
"@vue/shared": "3.5.35"
}
},
"node_modules/@vue/runtime-core": {
"version": "3.5.34",
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.34.tgz",
"integrity": "sha512-mKeBYvu8tcMSLhypAHBmriUFfWXKTCF/23Z4jiCoYK3UtWepkliViNLuR90V9XOyD62mUxs9p1jsrpK3CCGIzw==",
"version": "3.5.35",
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.35.tgz",
"integrity": "sha512-A/xFNX9loIcWDygeQuNCfKuh0CoYBzxhqEMNah5TSFg9Z53DrFYEN2qi5CU9necjM1OWYegYREUTHmXTmhfXtg==",
"license": "MIT",
"dependencies": {
"@vue/reactivity": "3.5.34",
"@vue/shared": "3.5.34"
"@vue/reactivity": "3.5.35",
"@vue/shared": "3.5.35"
}
},
"node_modules/@vue/runtime-dom": {
"version": "3.5.34",
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.34.tgz",
"integrity": "sha512-e8kZzERmCwUnBRVsgSQlAfrfU2rGoy0FFKPBXSlfEjc/O3KfA7QP0t1/2ZylrbchjmIKB4dPTd07A6WPr0eOrg==",
"version": "3.5.35",
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.35.tgz",
"integrity": "sha512-odrJ1C391dbGnyDRh8U+rnP7J2amIEzfmRk5vXy7xi3aZhEXofTvpi0T4HJb6jlNqQZTNPR5MPHSB3RHNkIORA==",
"license": "MIT",
"dependencies": {
"@vue/reactivity": "3.5.34",
"@vue/runtime-core": "3.5.34",
"@vue/shared": "3.5.34",
"@vue/reactivity": "3.5.35",
"@vue/runtime-core": "3.5.35",
"@vue/shared": "3.5.35",
"csstype": "^3.2.3"
}
},
"node_modules/@vue/server-renderer": {
"version": "3.5.34",
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.34.tgz",
"integrity": "sha512-nHxmJoTrKsmrkbILRhkC9gY1G3moZbJTqCzDd7DOOzG5KH9oeJ0Unqrff5f9v0pW//jES05ZkJcNtfE8JjOIew==",
"version": "3.5.35",
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.35.tgz",
"integrity": "sha512-NkebSOYdB97wi8OQcO3HqzZSlymJi/aWsN/7h74OSVhRTm6qGs3Jp3e0rCXynmWwSlKeRrnlIug+ilYoHBmQDA==",
"license": "MIT",
"dependencies": {
"@vue/compiler-ssr": "3.5.34",
"@vue/shared": "3.5.34"
"@vue/compiler-ssr": "3.5.35",
"@vue/shared": "3.5.35"
},
"peerDependencies": {
"vue": "3.5.34"
"vue": "3.5.35"
}
},
"node_modules/@vue/shared": {
"version": "3.5.34",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.34.tgz",
"integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==",
"version": "3.5.35",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.35.tgz",
"integrity": "sha512-zSbjL7gRXwks2ZQLRGCajBtBXEOXW9Ddhn/HvSdrGkE2dqGnumzW8XtusRrxrE9LvqtiqDXQ+A60Hp6mvdYxfA==",
"license": "MIT"
},
"node_modules/@vue/tsconfig": {
......@@ -1224,9 +1223,9 @@
}
},
"node_modules/ansis": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansis/-/ansis-4.3.0.tgz",
"integrity": "sha512-44mvgtPvohuU/70DdY5Oz2AIrLJ9k6/5x4KmoSvPwO+5Moijo0+N9D0fKbbYZQWP1hNm5CpOf+E01jhxG/r8xg==",
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/ansis/-/ansis-4.3.1.tgz",
"integrity": "sha512-BJ8/l4R5LRE7hW9WdSuGYrLSHi2ynxeFpDFbH0K/CgNeY/tyhk+vO6TYxXC5r5CpUhNVX310xzPsN/H9lCdfOA==",
"dev": true,
"license": "ISC",
"engines": {
......@@ -1234,9 +1233,9 @@
}
},
"node_modules/baseline-browser-mapping": {
"version": "2.10.32",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.32.tgz",
"integrity": "sha512-wbPvpyjJPC0zdfdKXxqEL3Ea+bOMD/87X4lftiJkkaBiuG6ALQy1SLmEd7BSmVCuwCQsBrCamgBoLyfFDD1EPg==",
"version": "2.10.33",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.33.tgz",
"integrity": "sha512-bA6+tcSLpz2tIEdDXZPpPTIuxBcC4+w6SieaYyfigIa4h8GlFxbA17v22Vx3JUtuZQj9SgOsnbK+aTBzyDyEuw==",
"dev": true,
"license": "Apache-2.0",
"bin": {
......@@ -1455,9 +1454,9 @@
}
},
"node_modules/electron-to-chromium": {
"version": "1.5.362",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.362.tgz",
"integrity": "sha512-PUY2DrLvkjkUuWqq+KPL2iWshrJsZOcIojzRQ7eXFacc9dWga7MGMJAa15VbiejSZB1PAXaRLAiKgruHP8LB1w==",
"version": "1.5.368",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.368.tgz",
"integrity": "sha512-7RckJJK4uESJF9PxvfMWd3TGqIiieUTG4HxnKaKuIpGbcr+r2ZEB3g2gAhCP3Fqm42vJSzLfgab9eva/C4/XVw==",
"dev": true,
"license": "ISC"
},
......@@ -1587,6 +1586,19 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-in-ssh": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-in-ssh/-/is-in-ssh-1.0.0.tgz",
"integrity": "sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-inside-container": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
......@@ -1999,22 +2011,6 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/msgpack": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/msgpack/-/msgpack-1.0.3.tgz",
"integrity": "sha512-FX88+Pexuh+UItdqg68WhNPGPhqs57RlXAYyXNZ8eTQC/Tx5lzeIoxTxA2qAd7qU5a/crON5F0ADf4l6k2b7Jw==",
"hasInstallScript": true,
"dependencies": {
"nan": "^2.14.0"
},
"bin": {
"json2msgpack": "bin/json2msgpack",
"msgpack2json": "bin/msgpack2json"
},
"engines": {
"node": ">=0.12.7"
}
},
"node_modules/muggle-string": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz",
......@@ -2022,12 +2018,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/nan": {
"version": "2.27.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.27.0.tgz",
"integrity": "sha512-hC+0LidcL3XE4rp1C4H54KujgXKzbfyTngZTwBByQxsOxCEKZT0MPQ4hOKUH2jU1OYstqdDH4onyHPDzcV0XdQ==",
"license": "MIT"
},
"node_modules/nanoid": {
"version": "3.3.12",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
......@@ -2047,9 +2037,9 @@
}
},
"node_modules/node-releases": {
"version": "2.0.46",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.46.tgz",
"integrity": "sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ==",
"version": "2.0.47",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.47.tgz",
"integrity": "sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==",
"dev": true,
"license": "MIT",
"engines": {
......@@ -2093,6 +2083,20 @@
"npm": ">= 10"
}
},
"node_modules/obug": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/obug/-/obug-2.1.2.tgz",
"integrity": "sha512-AWGB9WFcRXOQs48Z/udjI5ZcZMHXwX8XPByNpOydgcGsDLIzjGizhoMWJyKAWze7AVW/2W1i+/gPX4YtKe5cyg==",
"dev": true,
"funding": [
"https://github.com/sponsors/sxzz",
"https://opencollective.com/debug"
],
"license": "MIT",
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/ohash": {
"version": "2.0.11",
"resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz",
......@@ -2101,19 +2105,21 @@
"license": "MIT"
},
"node_modules/open": {
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz",
"integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==",
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/open/-/open-11.0.0.tgz",
"integrity": "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==",
"dev": true,
"license": "MIT",
"dependencies": {
"default-browser": "^5.2.1",
"default-browser": "^5.4.0",
"define-lazy-prop": "^3.0.0",
"is-in-ssh": "^1.0.0",
"is-inside-container": "^1.0.0",
"wsl-utils": "^0.1.0"
"powershell-utils": "^0.1.0",
"wsl-utils": "^0.3.0"
},
"engines": {
"node": ">=18"
"node": ">=20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
......@@ -2210,6 +2216,19 @@
"node": "^10 || ^12 || >=14"
}
},
"node_modules/powershell-utils": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/powershell-utils/-/powershell-utils-0.1.0.tgz",
"integrity": "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/read-package-json-fast": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-4.0.0.tgz",
......@@ -2225,13 +2244,13 @@
}
},
"node_modules/rolldown": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.2.tgz",
"integrity": "sha512-oZx5zVDtVB44AW3eaifgDml1gWRDZGvjcfdxonE4swNPG98PrrXjaO/KrnUjzlMnztCCRVlUueA1kCXhARGk6g==",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.3.tgz",
"integrity": "sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@oxc-project/types": "=0.132.0",
"@oxc-project/types": "=0.133.0",
"@rolldown/pluginutils": "^1.0.0"
},
"bin": {
......@@ -2241,21 +2260,21 @@
"node": "^20.19.0 || >=22.12.0"
},
"optionalDependencies": {
"@rolldown/binding-android-arm64": "1.0.2",
"@rolldown/binding-darwin-arm64": "1.0.2",
"@rolldown/binding-darwin-x64": "1.0.2",
"@rolldown/binding-freebsd-x64": "1.0.2",
"@rolldown/binding-linux-arm-gnueabihf": "1.0.2",
"@rolldown/binding-linux-arm64-gnu": "1.0.2",
"@rolldown/binding-linux-arm64-musl": "1.0.2",
"@rolldown/binding-linux-ppc64-gnu": "1.0.2",
"@rolldown/binding-linux-s390x-gnu": "1.0.2",
"@rolldown/binding-linux-x64-gnu": "1.0.2",
"@rolldown/binding-linux-x64-musl": "1.0.2",
"@rolldown/binding-openharmony-arm64": "1.0.2",
"@rolldown/binding-wasm32-wasi": "1.0.2",
"@rolldown/binding-win32-arm64-msvc": "1.0.2",
"@rolldown/binding-win32-x64-msvc": "1.0.2"
"@rolldown/binding-android-arm64": "1.0.3",
"@rolldown/binding-darwin-arm64": "1.0.3",
"@rolldown/binding-darwin-x64": "1.0.3",
"@rolldown/binding-freebsd-x64": "1.0.3",
"@rolldown/binding-linux-arm-gnueabihf": "1.0.3",
"@rolldown/binding-linux-arm64-gnu": "1.0.3",
"@rolldown/binding-linux-arm64-musl": "1.0.3",
"@rolldown/binding-linux-ppc64-gnu": "1.0.3",
"@rolldown/binding-linux-s390x-gnu": "1.0.3",
"@rolldown/binding-linux-x64-gnu": "1.0.3",
"@rolldown/binding-linux-x64-musl": "1.0.3",
"@rolldown/binding-openharmony-arm64": "1.0.3",
"@rolldown/binding-wasm32-wasi": "1.0.3",
"@rolldown/binding-win32-arm64-msvc": "1.0.3",
"@rolldown/binding-win32-x64-msvc": "1.0.3"
}
},
"node_modules/run-applescript": {
......@@ -2370,9 +2389,9 @@
}
},
"node_modules/tinyglobby": {
"version": "0.2.16",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
"integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==",
"version": "0.2.17",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
"integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
"dev": true,
"license": "MIT",
"dependencies": {
......@@ -2419,9 +2438,9 @@
}
},
"node_modules/undici-types": {
"version": "7.16.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
"version": "7.18.2",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
"dev": true,
"license": "MIT"
},
......@@ -2474,17 +2493,17 @@
}
},
"node_modules/vite": {
"version": "8.0.14",
"resolved": "https://registry.npmjs.org/vite/-/vite-8.0.14.tgz",
"integrity": "sha512-s4BJJ+5y1pYL6Otw51FHhVJQhPnuRinKig64g/1+EUNaJsd3gCKdD31IPFvswUgW9/60QT9oFHbZHbQK5imcxw==",
"version": "8.0.16",
"resolved": "https://registry.npmjs.org/vite/-/vite-8.0.16.tgz",
"integrity": "sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==",
"dev": true,
"license": "MIT",
"dependencies": {
"lightningcss": "^1.32.0",
"picomatch": "^4.0.4",
"postcss": "^8.5.15",
"rolldown": "1.0.2",
"tinyglobby": "^0.2.16"
"rolldown": "1.0.3",
"tinyglobby": "^0.2.17"
},
"bin": {
"vite": "bin/vite.js"
......@@ -2551,56 +2570,62 @@
}
}
},
"node_modules/vite-hot-client": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/vite-hot-client/-/vite-hot-client-2.2.0.tgz",
"integrity": "sha512-76Zs9zrHbH7M7wqeyooGQKdX+yg0pQ0xuQ1PbFp4z5a0Lzn2e5IPFoCswnmqZ4GiwqB4Jo3WcDAMO9jARTJl8w==",
"node_modules/vite-dev-rpc": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/vite-dev-rpc/-/vite-dev-rpc-2.0.0.tgz",
"integrity": "sha512-yKwbTwdHKSD2k/aGqyWpPHepo45OQc8lH3/6IfT4ZqeKE26ooKvi4WIEKzqWav8v+9Is8u1k8q54hvOmqASazA==",
"dev": true,
"license": "MIT",
"dependencies": {
"birpc": "^4.0.0",
"vite-hot-client": "^2.2.0"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"vite": "^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 || ^8.0.0"
"vite": "^2.9.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.1 || ^7.0.0-0 || ^8.0.0"
}
},
"node_modules/vite-plugin-vue-devtools": {
"version": "8.1.2",
"resolved": "https://registry.npmjs.org/vite-plugin-vue-devtools/-/vite-plugin-vue-devtools-8.1.2.tgz",
"integrity": "sha512-gt5h1CNryR9Hy0tvhSbqY3j0F7aj0pGxBxWLa1lXSiZVkhdWDf0vbCOZyjh8ivFGE6FDHTGy3zkcZGlMZdVHig==",
"node_modules/vite-dev-rpc/node_modules/birpc": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/birpc/-/birpc-4.0.0.tgz",
"integrity": "sha512-LShSxJP0KTmd101b6DRyGBj57LZxSDYWKitQNW/mi8GRMvZb078Uf9+pveax1DrVL89vm7mWe+TovdI/UDOuPw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@vue/devtools-core": "^8.1.2",
"@vue/devtools-kit": "^8.1.2",
"@vue/devtools-shared": "^8.1.2",
"sirv": "^3.0.2",
"vite-plugin-inspect": "^11.3.3",
"vite-plugin-vue-inspector": "^6.0.0"
},
"engines": {
"node": ">=v14.21.3"
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/vite-hot-client": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/vite-hot-client/-/vite-hot-client-2.2.0.tgz",
"integrity": "sha512-76Zs9zrHbH7M7wqeyooGQKdX+yg0pQ0xuQ1PbFp4z5a0Lzn2e5IPFoCswnmqZ4GiwqB4Jo3WcDAMO9jARTJl8w==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
"vite": "^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 || ^8.0.0"
}
},
"node_modules/vite-plugin-vue-devtools/node_modules/vite-plugin-inspect": {
"version": "11.3.3",
"resolved": "https://registry.npmjs.org/vite-plugin-inspect/-/vite-plugin-inspect-11.3.3.tgz",
"integrity": "sha512-u2eV5La99oHoYPHE6UvbwgEqKKOQGz86wMg40CCosP6q8BkB6e5xPneZfYagK4ojPJSj5anHCrnvC20DpwVdRA==",
"node_modules/vite-plugin-inspect": {
"version": "11.4.1",
"resolved": "https://registry.npmjs.org/vite-plugin-inspect/-/vite-plugin-inspect-11.4.1.tgz",
"integrity": "sha512-ShOFe2PURXGvRS5OrgmOLZOCwDTD7dEBVt0tMpFPKb9AsvqXKCRGM8QgKrUbRbJYFXScHvDPpGRd28rYidC0tA==",
"dev": true,
"license": "MIT",
"dependencies": {
"ansis": "^4.1.0",
"debug": "^4.4.1",
"ansis": "^4.3.0",
"error-stack-parser-es": "^1.0.5",
"obug": "^2.1.1",
"ohash": "^2.0.11",
"open": "^10.2.0",
"perfect-debounce": "^2.0.0",
"sirv": "^3.0.1",
"unplugin-utils": "^0.3.0",
"vite-dev-rpc": "^1.1.0"
"open": "^11.0.0",
"perfect-debounce": "^2.1.0",
"sirv": "^3.0.2",
"unplugin-utils": "^0.3.1",
"vite-dev-rpc": "^2.0.0"
},
"engines": {
"node": ">=14"
......@@ -2609,7 +2634,7 @@
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"vite": "^6.0.0 || ^7.0.0-0"
"vite": "^6.0.0 || ^7.0.0-0 || ^8.0.0-0"
},
"peerDependenciesMeta": {
"@nuxt/kit": {
......@@ -2617,21 +2642,25 @@
}
}
},
"node_modules/vite-plugin-vue-devtools/node_modules/vite-plugin-inspect/node_modules/vite-dev-rpc": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/vite-dev-rpc/-/vite-dev-rpc-1.1.0.tgz",
"integrity": "sha512-pKXZlgoXGoE8sEKiKJSng4hI1sQ4wi5YT24FCrwrLt6opmkjlqPPVmiPWWJn8M8byMxRGzp1CrFuqQs4M/Z39A==",
"node_modules/vite-plugin-vue-devtools": {
"version": "8.1.2",
"resolved": "https://registry.npmjs.org/vite-plugin-vue-devtools/-/vite-plugin-vue-devtools-8.1.2.tgz",
"integrity": "sha512-gt5h1CNryR9Hy0tvhSbqY3j0F7aj0pGxBxWLa1lXSiZVkhdWDf0vbCOZyjh8ivFGE6FDHTGy3zkcZGlMZdVHig==",
"dev": true,
"license": "MIT",
"dependencies": {
"birpc": "^2.4.0",
"vite-hot-client": "^2.1.0"
"@vue/devtools-core": "^8.1.2",
"@vue/devtools-kit": "^8.1.2",
"@vue/devtools-shared": "^8.1.2",
"sirv": "^3.0.2",
"vite-plugin-inspect": "^11.3.3",
"vite-plugin-vue-inspector": "^6.0.0"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
"engines": {
"node": ">=v14.21.3"
},
"peerDependencies": {
"vite": "^2.9.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.1 || ^7.0.0-0"
"vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
"node_modules/vite-plugin-vue-inspector": {
......@@ -2663,16 +2692,16 @@
"license": "MIT"
},
"node_modules/vue": {
"version": "3.5.34",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.34.tgz",
"integrity": "sha512-WdLBG9gm02OgJIG9axd5Hpx0TFLdzVgfG2evFFu8Rur5O/IoGc5cMjnjh3tPL6GnRGsYvUhBSKVPYVcxRKpMCA==",
"version": "3.5.35",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.35.tgz",
"integrity": "sha512-cx89fnr+0kVGHiNFG6y6s0bdjypJRFNZn6x3WPstNdQR1bi1mbB7h4v5IBGTsPJU3nK1+0Iqj3Zf+hZWMieR4Q==",
"license": "MIT",
"dependencies": {
"@vue/compiler-dom": "3.5.34",
"@vue/compiler-sfc": "3.5.34",
"@vue/runtime-dom": "3.5.34",
"@vue/server-renderer": "3.5.34",
"@vue/shared": "3.5.34"
"@vue/compiler-dom": "3.5.35",
"@vue/compiler-sfc": "3.5.35",
"@vue/runtime-dom": "3.5.35",
"@vue/server-renderer": "3.5.35",
"@vue/shared": "3.5.35"
},
"peerDependencies": {
"typescript": "*"
......@@ -2699,14 +2728,14 @@
}
},
"node_modules/vue-tsc": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-3.3.2.tgz",
"integrity": "sha512-n7nQoA3YWW/eiDR8jMiv/uJvlg0uLGs+YgUrsTrf9EZaYSt3tuvMZb5V8+7Mvh/EH5pnY/hoVdgfjH+XcK+wwA==",
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-3.3.3.tgz",
"integrity": "sha512-SWUEG7YRUeDJHT7Xsuhf02elYX2gxPzzAII7OxDAh4KNOr4QHQ0Lls0YfnaO5GNd560CwVa2HTfdqmA5MqvRqQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@volar/typescript": "2.4.28",
"@vue/language-core": "3.3.2"
"@vue/language-core": "3.3.3"
},
"bin": {
"vue-tsc": "bin/vue-tsc.js"
......@@ -2753,16 +2782,17 @@
}
},
"node_modules/wsl-utils": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz",
"integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==",
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.3.1.tgz",
"integrity": "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-wsl": "^3.1.0"
"is-wsl": "^3.1.0",
"powershell-utils": "^0.1.0"
},
"engines": {
"node": ">=18"
"node": ">=20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
......
......@@ -13,7 +13,6 @@
"dependencies": {
"@msgpack/msgpack": "^3.1.3",
"crypto-js": "^4.2.0",
"msgpack": "^1.0.3",
"socket.io-client": "^4.8.3",
"vue": "^3.5.32",
"vue-router": "^4.6.4"
......
......@@ -117,7 +117,8 @@ onBeforeUnmount(() => {
<template>
<div class="design-stage-viewport" :style="{ background }">
<div class="design-stage" :style="stageStyle">
<div v-if="gameCountdownVisible" class="game-countdown">{{ gameCountdown }}</div>
<div v-if="gameCountdownVisible" class="game-countdown">
倒计时: &nbsp;{{ gameCountdown }}</div>
<div v-if="countdownVisible" class="countdown-modal">
<div :key="countdownKey" class="countdown-number">{{ countdown }}</div>
</div>
......@@ -159,16 +160,14 @@ onBeforeUnmount(() => {
top: 64px;
right: 80px;
z-index: 10;
min-width: 220px;
height: 132px;
width: 300px;
height: 84px;
padding: 0 40px;
border: 6px solid rgba(255, 255, 255, 0.85);
border-radius: 66px;
background: rgba(0, 0, 0, 0.42);
border: 1px dashed #ccc;
color: #fff;
font-size: 92px;
font-weight: 800;
line-height: 120px;
font-size: 42px;
line-height: 84px;
text-align: center;
box-shadow: 0 18px 42px rgba(0, 0, 0, 0.25);
text-shadow: 0 8px 18px rgba(0, 0, 0, 0.4);
......
......@@ -9,7 +9,22 @@ const imageUrls = {
bg1: cssAssetUrl('main-bg1.png'),
logo: cssAssetUrl('game1/logo.png'),
title1: cssAssetUrl('main-title.png'),
icon1: cssAssetUrl('icon1.png'),
icon2: cssAssetUrl('icon2.png'),
icon3: cssAssetUrl('icon3.png'),
icon4: cssAssetUrl('icon4.png'),
icon5: cssAssetUrl('icon5.png'),
icon6: cssAssetUrl('icon6.png'),
}
const iconUrls = [
imageUrls.icon1,
imageUrls.icon2,
imageUrls.icon3,
imageUrls.icon4,
imageUrls.icon5,
imageUrls.icon6,
]
const list = ref(['击鼓齐福', '聚宝接福',
'马上有福', '策马迎福', '圈彩纳福', '福运当头'
......@@ -49,7 +64,7 @@ const loginSuccessHandler = () => {
<div v-for="item, index in list" @click="gameHandler(index)">
<div class="card">
<div class="img">
<div></div>
<div :style="{ background: `${iconUrls[index]} center / cover no-repeat` }"></div>
</div>
<div class="btn">{{ item }}</div>
</div>
......@@ -153,13 +168,10 @@ const loginSuccessHandler = () => {
transition: transform 0.2s ease 0.1s;
>div {
width: calc(100% - 20px);
height: calc(100% - 20px);
border: 1px solid red;
width: 100%;
height: 100%;
border-radius: 20px;
position: absolute;
left: 10px;
top: 10px;
}
}
......
......@@ -148,7 +148,6 @@ const { startGame, createRoom, backRoom } = useAdminGameSocket({
onRelogin: async () => {
$remove_socket_storage();
await router.replace('/')
debugger
}
})
......
......@@ -141,7 +141,7 @@ function handleRoomState(data: any) {
switch (data?.status) {
case 0:
gotoLoading(true);
createRoom(1);
createRoom(4);
break;
case 1:
gotoLoading();
......
......@@ -121,7 +121,7 @@ function handleRoomState(data: any) {
switch (data?.status) {
case 0:
gotoLoading(true)
createRoom(1)
createRoom(6)
break
case 1:
gotoLoading()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment