Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
F
fc-minigame
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
陈冲
fc-minigame
Commits
a8efe97a
Commit
a8efe97a
authored
Jun 08, 2026
by
陈冲
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 功能修复
parent
c1dbe1ba
Show whitespace changes
Inline
Side-by-side
Showing
30 changed files
with
862 additions
and
319 deletions
+862
-319
socket_io.rs
backend/src/protocols/socket_io.rs
+99
-25
index.html
frontend-h5/index.html
+1
-1
base.css
frontend-h5/src/assets/base.css
+1
-0
ws.ts
frontend-h5/src/commons/ws.ts
+5
-3
MobileStage.vue
frontend-h5/src/components/MobileStage.vue
+1
-1
useGameSocket.ts
frontend-h5/src/composables/useGameSocket.ts
+14
-6
Game.vue
frontend-h5/src/pages/game1/Game.vue
+8
-11
LoadingView.vue
frontend-h5/src/pages/game1/views/LoadingView.vue
+1
-1
Game4.vue
frontend-h5/src/pages/game4/Game4.vue
+30
-34
Game5.vue
frontend-h5/src/pages/game5/Game5.vue
+11
-12
LoadingView.vue
frontend-h5/src/pages/game5/views/LoadingView.vue
+1
-0
Game.vue
frontend-h5/src/pages/game6/Game.vue
+15
-11
LoadingView.vue
frontend-h5/src/pages/game6/views/LoadingView.vue
+1
-1
vite.config.ts
frontend-h5/vite.config.ts
+1
-1
applause.mp3
frontend-large/src/assets/images/applause.mp3
+0
-0
game1.mp3
frontend-large/src/assets/images/game1.mp3
+0
-0
music.ts
frontend-large/src/commons/music.ts
+88
-1
ws.ts
frontend-large/src/commons/ws.ts
+2
-2
useAdminGameSocket.ts
frontend-large/src/composables/useAdminGameSocket.ts
+31
-11
Login.vue
frontend-large/src/pages/Login.vue
+47
-11
Main.vue
frontend-large/src/pages/Main.vue
+20
-3
Game.vue
frontend-large/src/pages/game1/Game.vue
+20
-10
Game4.vue
frontend-large/src/pages/game4/Game4.vue
+362
-132
LoadingView.vue
frontend-large/src/pages/game4/views/LoadingView.vue
+27
-18
Game5.vue
frontend-large/src/pages/game5/Game5.vue
+27
-9
LoadingView.vue
frontend-large/src/pages/game5/views/LoadingView.vue
+22
-7
Game.vue
frontend-large/src/pages/game6/Game.vue
+14
-5
Rank2View.vue
frontend-large/src/pages/game6/views/Rank2View.vue
+1
-1
index.ts
frontend-large/src/router/index.ts
+11
-1
vite.config.ts
frontend-large/vite.config.ts
+1
-1
No files found.
backend/src/protocols/socket_io.rs
View file @
a8efe97a
...
@@ -14,8 +14,8 @@ use std::sync::atomic::{AtomicU64, Ordering};
...
@@ -14,8 +14,8 @@ use std::sync::atomic::{AtomicU64, Ordering};
use
std
::
time
::{
Duration
,
Instant
};
use
std
::
time
::{
Duration
,
Instant
};
lazy_static
::
lazy_static!
{
lazy_static
::
lazy_static!
{
///
可以有多个管理员,但不要用同一个账户登录,否则后面的没效果
///
当前唯一在线管理员:(token, socket)。
static
ref
CLIENT_ADMIN_
MAP
:
DashMap
<
String
,
SocketRef
>
=
DashMap
::
new
(
);
static
ref
CLIENT_ADMIN_
SESSION
:
std
::
sync
::
Mutex
<
Option
<
(
String
,
SocketRef
)
>>
=
std
::
sync
::
Mutex
::
new
(
None
);
static
ref
CLIENT_PLAYER_MAP
:
DashMap
<
String
,
(
i32
,
SocketRef
)
>
=
DashMap
::
new
();
// 1: 正在游戏中
static
ref
CLIENT_PLAYER_MAP
:
DashMap
<
String
,
(
i32
,
SocketRef
)
>
=
DashMap
::
new
();
// 1: 正在游戏中
static
ref
ROOM_STATE
:
std
::
sync
::
Mutex
<
RoomState
>
=
std
::
sync
::
Mutex
::
new
(
RoomState
::
default
());
static
ref
ROOM_STATE
:
std
::
sync
::
Mutex
<
RoomState
>
=
std
::
sync
::
Mutex
::
new
(
RoomState
::
default
());
}
}
...
@@ -234,7 +234,10 @@ pub fn get_player_count() -> usize {
...
@@ -234,7 +234,10 @@ pub fn get_player_count() -> usize {
}
}
// 获取管理员数量
// 获取管理员数量
pub
fn
get_admin_count
()
->
usize
{
pub
fn
get_admin_count
()
->
usize
{
CLIENT_ADMIN_MAP
.len
()
CLIENT_ADMIN_SESSION
.lock
()
.map
(|
session
|
usize
::
from
(
session
.is_some
()))
.unwrap_or
(
0
)
}
}
pub
fn
emit_to_user
(
userid
:
&
str
,
event
:
&
str
,
payload
:
&
Value
)
{
pub
fn
emit_to_user
(
userid
:
&
str
,
event
:
&
str
,
payload
:
&
Value
)
{
...
@@ -295,11 +298,46 @@ fn broadcast_msgpack_all_player(event: &str, payload: &Value) {
...
@@ -295,11 +298,46 @@ fn broadcast_msgpack_all_player(event: &str, payload: &Value) {
}
}
/// 发送给所有管理员
/// 发送给所有管理员
fn
broadcast_msgpack_all_admin
(
event
:
&
str
,
payload
:
&
Value
)
{
fn
broadcast_msgpack_all_admin
(
event
:
&
str
,
payload
:
&
Value
)
{
if
let
Some
(
payload
)
=
encode_msgpack
(
payload
)
{
let
Some
(
payload
)
=
encode_msgpack
(
payload
)
else
{
for
socket
in
CLIENT_ADMIN_MAP
.iter
()
{
return
;
_
=
socket
.value
()
.emit
(
event
,
&
payload
);
};
let
socket
=
CLIENT_ADMIN_SESSION
.lock
()
.ok
()
.and_then
(|
session
|
session
.as_ref
()
.map
(|(
_
,
socket
)|
socket
.clone
()));
if
let
Some
(
socket
)
=
socket
{
_
=
socket
.emit
(
event
,
&
payload
);
}
}
}
fn
replace_current_admin
(
userid
:
String
,
socket
:
SocketRef
)
->
Result
<
Option
<
SocketRef
>
,
()
>
{
CLIENT_ADMIN_SESSION
.lock
()
.map
(|
mut
session
|
{
let
old_socket
=
session
.take
()
.map
(|(
_
,
socket
)|
socket
);
*
session
=
Some
((
userid
,
socket
));
old_socket
})
.map_err
(|
_
|
())
}
fn
clear_current_admin_if_match
(
userid
:
&
str
,
socket
:
&
SocketRef
)
->
bool
{
CLIENT_ADMIN_SESSION
.lock
()
.map
(|
mut
session
|
{
let
should_clear
=
session
.as_ref
()
.map
(|(
current_userid
,
current_socket
)|
{
current_userid
==
userid
&&
current_socket
.id
==
socket
.id
})
.unwrap_or
(
false
);
if
should_clear
{
*
session
=
None
;
}
}
should_clear
})
.unwrap_or
(
false
)
}
}
/// 发送给所有管理员和玩家
/// 发送给所有管理员和玩家
fn
broadcast_msgpack_all
(
event
:
&
str
,
payload
:
&
Value
)
{
fn
broadcast_msgpack_all
(
event
:
&
str
,
payload
:
&
Value
)
{
...
@@ -503,6 +541,8 @@ async fn handle_room_command(
...
@@ -503,6 +541,8 @@ async fn handle_room_command(
emit_msgpack
(
&
socket
,
evt
,
&
ok_resp
(
Some
(
json!
(
index
))));
emit_msgpack
(
&
socket
,
evt
,
&
ok_resp
(
Some
(
json!
(
index
))));
if
cmd
==
"room_back"
{
if
cmd
==
"room_back"
{
broadcast_msgpack_all_player
(
evt
,
&
ok_resp
(
Some
(
json!
(
index
))));
broadcast_msgpack_all_player
(
evt
,
&
ok_resp
(
Some
(
json!
(
index
))));
}
else
if
cmd
==
"room_create"
{
broadcast_msgpack_all_player
(
evt
,
&
ok_resp
(
Some
(
json!
(
index
))));
}
}
}
}
}
}
...
@@ -534,6 +574,10 @@ async fn handle_room_command(
...
@@ -534,6 +574,10 @@ async fn handle_room_command(
.to_string
();
.to_string
();
if
let
Ok
(
mut
state
)
=
ROOM_STATE
.lock
()
{
if
let
Ok
(
mut
state
)
=
ROOM_STATE
.lock
()
{
// dbg!(
// &state.current_game_id.clone(),
// &state.status.clone().as_str()
// );
let
Some
(
current_game_id
)
=
state
.current_game_id
.clone
()
else
{
let
Some
(
current_game_id
)
=
state
.current_game_id
.clone
()
else
{
drop
(
state
);
drop
(
state
);
return
;
return
;
...
@@ -773,17 +817,30 @@ async fn handle_room_command(
...
@@ -773,17 +817,30 @@ async fn handle_room_command(
if
!
is_admin
{
if
!
is_admin
{
return
;
return
;
}
}
let
mut
status
=
""
.to_string
();
let
mut
title
=
""
.to_string
();
if
let
Ok
(
mut
state
)
=
ROOM_STATE
.lock
()
{
if
let
Ok
(
mut
state
)
=
ROOM_STATE
.lock
()
{
status
=
state
.current_game_id
.clone
()
.unwrap_or_default
();
title
=
get_game_tilte
(
&
status
);
state
.reset
();
state
.reset
();
drop
(
state
);
drop
(
state
);
}
}
broadcast_msgpack_all_player
(
evt
,
&
json!
({}));
broadcast_msgpack_all_player
(
evt
,
&
err_resp
(
&
format!
(
"管理员关闭了 {} 该房间"
,
title
),
Some
(
json!
(
status
)),
),
);
broadcast_room_rank
(
Vec
::
new
());
broadcast_room_rank
(
Vec
::
new
());
emit_msgpack
(
&
socket
,
evt
,
&
ok_resp
(
None
));
emit_msgpack
(
&
socket
,
evt
,
&
ok_resp
(
None
));
}
}
// 获取房间状态
// 获取房间状态
"room_state"
=>
{
"room_state"
=>
{
if
let
Ok
(
state
)
=
ROOM_STATE
.lock
()
{
if
let
Ok
(
state
)
=
ROOM_STATE
.lock
()
{
let
gameId
=
state
.current_game_id
.clone
()
.unwrap_or_default
();
let
count
=
state
.players
.len
();
let
count
=
state
.players
.len
();
let
ranking
=
state
.current_ranking_payload
();
let
ranking
=
state
.current_ranking_payload
();
let
status
=
state
.status
as
i32
;
let
status
=
state
.status
as
i32
;
...
@@ -792,7 +849,9 @@ async fn handle_room_command(
...
@@ -792,7 +849,9 @@ async fn handle_room_command(
emit_msgpack
(
emit_msgpack
(
&
socket
,
&
socket
,
evt
,
evt
,
&
ok_resp
(
Some
(
json!
({
"status"
:
status
,
"list"
:
ranking
,
"count"
:
count
}))),
&
ok_resp
(
Some
(
json!
({
"status"
:
status
,
"list"
:
ranking
,
"count"
:
count
,
"gameId"
:
gameId
,}),
)),
);
);
}
}
}
}
...
@@ -858,24 +917,25 @@ pub async fn on_connect(_io: SocketIo, socket: SocketRef, Data(data): Data<Value
...
@@ -858,24 +917,25 @@ pub async fn on_connect(_io: SocketIo, socket: SocketRef, Data(data): Data<Value
return
;
return
;
}
}
}
}
// 原子检查加写入,避免并发下同一个 userid 同时登录。
if
is_admin
{
if
is_admin
{
match
CLIENT_ADMIN_MAP
.entry
(
userid
.clone
())
{
match
replace_current_admin
(
userid
.clone
(),
socket
.clone
())
{
Entry
::
Occupied
(
_
)
=>
{
Ok
(
Some
(
old_socket
)
)
=>
{
emit_msgpack
(
emit_msgpack
(
&
socket
,
&
old_
socket
,
"
log
in_result"
,
"
new_adm
in_result"
,
&
err_resp
(
"
当前管理员账号已登录,不能重复登录"
,
Some
(
json!
(
1
))
),
&
err_resp
(
"
有其他管理员登录,您已下线"
,
None
),
);
);
_
=
old_socket
.disconnect
();
}
Ok
(
None
)
=>
{}
Err
(
_
)
=>
{
_
=
socket
.disconnect
();
_
=
socket
.disconnect
();
return
;
return
;
}
}
Entry
::
Vacant
(
entry
)
=>
{
entry
.insert
(
socket
.clone
());
}
}
}
}
else
{
}
else
{
if
CLIENT_ADMIN_MAP
.is_empty
()
{
if
get_admin_count
()
==
0
{
emit_msgpack
(
emit_msgpack
(
&
socket
,
&
socket
,
"connect_result"
,
"connect_result"
,
...
@@ -896,7 +956,6 @@ pub async fn on_connect(_io: SocketIo, socket: SocketRef, Data(data): Data<Value
...
@@ -896,7 +956,6 @@ pub async fn on_connect(_io: SocketIo, socket: SocketRef, Data(data): Data<Value
}
}
}
}
}
}
// dbg!(&is_admin,&userid);
// 鉴权通过后,在这里挂玩家消息事件处理器。
// 鉴权通过后,在这里挂玩家消息事件处理器。
let
message_userid
=
userid
.clone
();
let
message_userid
=
userid
.clone
();
socket
.on
(
"message"
,
move
|
socket
:
SocketRef
,
data
:
Data
<
Bytes
>
|
{
socket
.on
(
"message"
,
move
|
socket
:
SocketRef
,
data
:
Data
<
Bytes
>
|
{
...
@@ -921,9 +980,11 @@ pub async fn on_connect(_io: SocketIo, socket: SocketRef, Data(data): Data<Value
...
@@ -921,9 +980,11 @@ pub async fn on_connect(_io: SocketIo, socket: SocketRef, Data(data): Data<Value
move
|
socket
:
SocketRef
,
_reason
:
DisconnectReason
|
async
move
{
move
|
socket
:
SocketRef
,
_reason
:
DisconnectReason
|
async
move
{
if
!
is_create_user
{
if
!
is_create_user
{
if
is_admin
{
if
is_admin
{
CLIENT_ADMIN_MAP
.remove
(
&
userid
);
if
!
clear_current_admin_if_match
(
&
userid
,
&
socket
)
{
return
;
}
// 前端页面刷新时房间状态丢失体验会不好
// 前端页面刷新时房间状态丢失体验会不好
if
CLIENT_ADMIN_MAP
.is_empty
()
{
if
get_admin_count
()
==
0
{
if
let
Ok
(
mut
state
)
=
ROOM_STATE
.lock
()
{
if
let
Ok
(
mut
state
)
=
ROOM_STATE
.lock
()
{
state
.reset
();
// 如果管理员都退出了,就把房间状态重置。
state
.reset
();
// 如果管理员都退出了,就把房间状态重置。
drop
(
state
);
drop
(
state
);
...
@@ -1013,12 +1074,25 @@ pub async fn login(req: &mut Request, res: &mut Response) {
...
@@ -1013,12 +1074,25 @@ pub async fn login(req: &mut Request, res: &mut Response) {
res
.render
(
Json
(
err_resp
(
"用户名或密码不能为空"
,
None
)));
res
.render
(
Json
(
err_resp
(
"用户名或密码不能为空"
,
None
)));
return
;
return
;
}
}
//当前管理员已登录,不能重复登录
if
get_admin_count
()
>
0
{
if
(
CLIENT_ADMIN_MAP
.contains_key
(
&
manager
.token
))
{
if
let
Ok
(
state
)
=
ROOM_STATE
.lock
()
{
res
.render
(
Json
(
err_resp
(
"当前管理员已登录,不能重复登录"
,
None
)));
let
game_id
=
state
.current_game_id
.clone
()
.unwrap_or
(
""
.to_string
());
if
matches!
(
state
.status
,
RoomStatus
::
Start
|
RoomStatus
::
Running
|
RoomStatus
::
Submit
)
{
drop
(
state
);
res
.render
(
Json
(
err_resp
(
&
format!
(
"当前管理员已开启游戏房间 - {},请稍后再登录"
,
get_game_tilte
(
&
game_id
)
),
None
,
)));
return
;
return
;
}
}
}
}
res
.render
(
Json
(
ok_resp
(
Some
(
json!
({
res
.render
(
Json
(
ok_resp
(
Some
(
json!
({
"passphrase"
:
passphrase
,
"passphrase"
:
passphrase
,
"token"
:
manager
.token
,
"token"
:
manager
.token
,
...
...
frontend-h5/index.html
View file @
a8efe97a
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
<html
lang=
"zh-CN"
>
<html
lang=
"zh-CN"
>
<head>
<head>
<meta
charset=
"UTF-8"
>
<meta
charset=
"UTF-8"
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1
.0, viewport-fit=cover
"
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1
, maximum-scale=1, minimum-scale=1, user-scalable=no
"
>
<title>
小游戏-H5
</title>
<title>
小游戏-H5
</title>
<style>body
{
background
:
#FA6047
;}
</style>
<style>body
{
background
:
#FA6047
;}
</style>
<script>
localStorage
.
setItem
(
'domain'
,
''
);
</script>
<script>
localStorage
.
setItem
(
'domain'
,
''
);
</script>
...
...
frontend-h5/src/assets/base.css
View file @
a8efe97a
...
@@ -21,6 +21,7 @@ html,
...
@@ -21,6 +21,7 @@ html,
body
{
body
{
width
:
100%
;
width
:
100%
;
height
:
100%
;
height
:
100%
;
touch-action
:
manipulation
;
}
}
body
{
body
{
...
...
frontend-h5/src/commons/ws.ts
View file @
a8efe97a
...
@@ -67,8 +67,8 @@ export function initSocket(args: SocketInitArgs): Socket | null {
...
@@ -67,8 +67,8 @@ export function initSocket(args: SocketInitArgs): Socket | null {
});
});
socket
.
onAny
((
evt
,
payload
)
=>
{
socket
.
onAny
((
evt
,
payload
)
=>
{
const
data
=
decode
(
payload
);
const
data
=
decode
(
payload
);
if
(
$is_run_local
())
{
if
(
$is_run_local
())
{
console
.
log
(
evt
,
data
);
console
.
log
(
"recv<============"
,
evt
,
data
);
}
}
messageHandlers
.
forEach
((
handler
)
=>
handler
(
evt
,
data
));
messageHandlers
.
forEach
((
handler
)
=>
handler
(
evt
,
data
));
});
});
...
@@ -94,7 +94,9 @@ export function sendSocketMessage(cmd: string, data: any = {}): boolean {
...
@@ -94,7 +94,9 @@ export function sendSocketMessage(cmd: string, data: any = {}): boolean {
}
}
return
false
;
return
false
;
}
}
if
(
$is_run_local
())
{
console
.
log
(
'================>send'
,
cmd
,
data
);
}
socket
.
send
(
encode
({
cmd
,
data
}));
socket
.
send
(
encode
({
cmd
,
data
}));
return
true
;
return
true
;
}
}
...
...
frontend-h5/src/components/MobileStage.vue
View file @
a8efe97a
...
@@ -16,7 +16,7 @@ const props = withDefaults(defineProps<{
...
@@ -16,7 +16,7 @@ const props = withDefaults(defineProps<{
height
:
1624
,
height
:
1624
,
mode
:
'contain'
,
mode
:
'contain'
,
backgroundMode
:
'cover'
,
backgroundMode
:
'cover'
,
showGameRule
:
false
,
showGameRule
:
true
,
//玩家要有操作动作才能播放音乐,这里会默认显示游戏规则,让玩家有关闭操作
showGameRank
:
false
showGameRank
:
false
})
})
...
...
frontend-h5/src/composables/useGameSocket.ts
View file @
a8efe97a
...
@@ -91,6 +91,12 @@ export function useGameSocket(options: GameSocketOptions) {
...
@@ -91,6 +91,12 @@ export function useGameSocket(options: GameSocketOptions) {
resubmitcount
++
;
resubmitcount
++
;
options
.
onRescoreSubmitted
?.(
resubmitcount
);
options
.
onRescoreSubmitted
?.(
resubmitcount
);
},
200
);
},
200
);
}
else
if
(
evt
==
'room_close_result'
)
{
userJoinStatus
.
value
=
false
if
(
data
==
options
.
gameId
)
{
options
.
onRoomClosed
?.(
data
)
}
return
;
}
}
return
;
return
;
}
}
...
@@ -101,11 +107,15 @@ export function useGameSocket(options: GameSocketOptions) {
...
@@ -101,11 +107,15 @@ export function useGameSocket(options: GameSocketOptions) {
}
}
switch
(
evt
)
{
switch
(
evt
)
{
case
'connect_result'
:{
case
'connect_result'
:
{
debugger
debugger
break
;
break
;
}
}
case
'room_create_result'
:
{
case
'room_create_result'
:
{
if
(
`game
${
data
}
`
==
options
.
gameId
)
{
location
.
reload
();
return
;
}
const
nextPath
=
getGameHomePath
(
data
)
const
nextPath
=
getGameHomePath
(
data
)
if
(
nextPath
&&
router
.
currentRoute
.
value
.
path
!==
nextPath
)
{
if
(
nextPath
&&
router
.
currentRoute
.
value
.
path
!==
nextPath
)
{
...
@@ -153,15 +163,13 @@ export function useGameSocket(options: GameSocketOptions) {
...
@@ -153,15 +163,13 @@ export function useGameSocket(options: GameSocketOptions) {
options
.
onScoreSubmitted
?.(
true
,
data
)
options
.
onScoreSubmitted
?.(
true
,
data
)
break
break
}
}
case
'room_close_result'
:
{
userJoinStatus
.
value
=
false
options
.
onRoomClosed
?.(
data
)
break
}
case
'room_back_result'
:
{
case
'room_back_result'
:
{
options
.
onRoomBack
?.(
data
);
options
.
onRoomBack
?.(
data
);
break
;
break
;
}
}
default
:
{
debugger
}
}
}
options
.
onEvent
?.(
evt
,
payload
)
options
.
onEvent
?.(
evt
,
payload
)
...
...
frontend-h5/src/pages/game1/Game.vue
View file @
a8efe97a
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
onBeforeUnmount
,
onMounted
,
ref
}
from
'vue'
import
{
onBeforeUnmount
,
onMounted
,
ref
,
watch
}
from
'vue'
import
{
cssAssetUrl
}
from
'@/commons/assets.ts'
import
{
cssAssetUrl
}
from
'@/commons/assets.ts'
import
MobileStage
from
'@/components/MobileStage.vue'
import
MobileStage
from
'@/components/MobileStage.vue'
import
{
useGameSocket
,
joinSharedRoom
,
sendGameMessage
,
userJoinStatus
}
from
'@/composables/useGameSocket'
import
{
useGameSocket
,
joinSharedRoom
,
sendGameMessage
,
userJoinStatus
}
from
'@/composables/useGameSocket'
...
@@ -42,7 +42,7 @@ const isGuPlaying = ref(false)
...
@@ -42,7 +42,7 @@ const isGuPlaying = ref(false)
const
token
=
ref
(
wechat
?.
token
??
''
)
const
token
=
ref
(
wechat
?.
token
??
''
)
const
nickname
=
ref
(
wechat
?.
nickname
??
''
)
const
nickname
=
ref
(
wechat
?.
nickname
??
''
)
const
avatar
=
ref
(
wechat
?.
avatar
??
''
)
const
avatar
=
ref
(
wechat
?.
avatar
??
''
)
const
showGameRule
=
ref
(
fals
e
)
const
showGameRule
=
ref
(
tru
e
)
const
mobileStageRef
=
ref
<
InstanceType
<
typeof
MobileStage
>
|
null
>
(
null
)
const
mobileStageRef
=
ref
<
InstanceType
<
typeof
MobileStage
>
|
null
>
(
null
)
const
_offSocketMessage
=
ref
<
(()
=>
void
)
|
undefined
>
()
const
_offSocketMessage
=
ref
<
(()
=>
void
)
|
undefined
>
()
...
@@ -261,9 +261,9 @@ const showGameRuleHandler = () => {
...
@@ -261,9 +261,9 @@ const showGameRuleHandler = () => {
4.禁止外挂,作弊,违规账号取消成绩与领奖资格;
<br
/><br
/>
4.禁止外挂,作弊,违规账号取消成绩与领奖资格;
<br
/><br
/>
祝您游戏愉快!
祝您游戏愉快!
</div>
</div>
</div>
<div
class=
"rule-close"
@
click=
"showGameRuleHandler"
></div>
<div
class=
"rule-close"
@
click=
"showGameRuleHandler"
></div>
</div>
</div>
</div>
</
template
>
</
template
>
<LoadingView
v-if=
"currentView === 'loading'"
:image-urls=
"imageUrls"
:user-join-status=
"userJoinStatus"
<LoadingView
v-if=
"currentView === 'loading'"
:image-urls=
"imageUrls"
:user-join-status=
"userJoinStatus"
@
touchGameRule=
"showGameRuleHandler"
/>
@
touchGameRule=
"showGameRuleHandler"
/>
...
@@ -279,12 +279,9 @@ const showGameRuleHandler = () => {
...
@@ -279,12 +279,9 @@ const showGameRuleHandler = () => {
<
style
scoped
>
<
style
scoped
>
.rule-container
{
.rule-container
{
.rule-txt-container
{
.rule-txt-container
{
position
:
absolute
;
background
:
v-bind
(
'imageUrls.rule'
)
center
/
cover
no-repeat
;
background
:
v-bind
(
'imageUrls.rule'
)
center
/
cover
no-repeat
;
width
:
692px
;
width
:
692px
;
height
:
797px
;
height
:
797px
;
left
:
-157px
;
top
:
-75px
;
transform
:
scale
(
0.5
);
transform
:
scale
(
0.5
);
.rule-title
{
.rule-title
{
...
@@ -307,11 +304,11 @@ const showGameRuleHandler = () => {
...
@@ -307,11 +304,11 @@ const showGameRuleHandler = () => {
.rule-close
{
.rule-close
{
width
:
57px
;
width
:
57px
;
height
:
57px
;
height
:
57px
;
margin
:
0
auto
;
background
:
v-bind
(
'imageUrls.close'
)
center
/
cover
no-repeat
;
margin-top
:
450px
;
transform
:
translateX
(
-50%
)
scale
(
1.4
)
;
background
:
v-bind
(
'imageUrls.close'
)
center
/
cover
;
position
:
absolute
;
position
:
relative
;
bottom
:
-75px
;
transform
:
scale
(
0.8
)
;
left
:
50%
;
}
}
}
}
</
style
>
</
style
>
frontend-h5/src/pages/game1/views/LoadingView.vue
View file @
a8efe97a
...
@@ -23,7 +23,7 @@ onMounted(() => {
...
@@ -23,7 +23,7 @@ onMounted(() => {
<div
class=
"img-avatar"
:style=
"`background: url($
{avatar});border-radius:66px;width:132px;height:132px;`">
<div
class=
"img-avatar"
:style=
"`background: url($
{avatar});border-radius:66px;width:132px;height:132px;`">
</div>
</div>
<div
class=
"txt-nickname"
>
{{
nickname
}}
</div>
<div
class=
"txt-nickname"
>
{{
nickname
}}
</div>
<div
class=
"txt-loading"
>
您已成功加入游戏等待主持人开始
</div>
<div
class=
"txt-loading"
v-if=
"userJoinStatus"
>
您已成功加入游戏等待主持人开始
</div>
<div
class=
"txt-loading2"
>
游戏即将开始 敬请期待
</div>
<div
class=
"txt-loading2"
>
游戏即将开始 敬请期待
</div>
<div
class=
"bg-bottom"
></div>
<div
class=
"bg-bottom"
></div>
<div
class=
"loading-gu"
></div>
<div
class=
"loading-gu"
></div>
...
...
frontend-h5/src/pages/game4/Game4.vue
View file @
a8efe97a
...
@@ -8,6 +8,7 @@ import PlayingView from './views/PlayingView.vue'
...
@@ -8,6 +8,7 @@ import PlayingView from './views/PlayingView.vue'
import
ScoreView
from
'./views/ScoreView.vue'
import
ScoreView
from
'./views/ScoreView.vue'
import
{
$getWechat
}
from
'@/commons/utils.ts'
import
{
$getWechat
}
from
'@/commons/utils.ts'
const
gameId
=
'game4'
;
type
GameView
=
'loading'
|
'playing'
|
'score'
type
GameView
=
'loading'
|
'playing'
|
'score'
const
imageUrls
=
{
const
imageUrls
=
{
...
@@ -30,7 +31,9 @@ const imageUrls = {
...
@@ -30,7 +31,9 @@ const imageUrls = {
scoreBg
:
cssAssetUrl
(
'game1/score-bg.png'
),
scoreBg
:
cssAssetUrl
(
'game1/score-bg.png'
),
back
:
cssAssetUrl
(
'game4/back.svg'
),
back
:
cssAssetUrl
(
'game4/back.svg'
),
replay
:
cssAssetUrl
(
'game4/replay.svg'
),
replay
:
cssAssetUrl
(
'game4/replay.svg'
),
close
:
cssAssetUrl
(
'game4/h5-game4-close.svg'
),
close
:
cssAssetUrl
(
'game1/close.png'
),
rule
:
cssAssetUrl
(
'game1/rule.png'
)
}
}
const
wechat
=
$getWechat
()
const
wechat
=
$getWechat
()
...
@@ -52,7 +55,7 @@ const currentYaoyiyao = ref(imageUrls.yaoyiyao)
...
@@ -52,7 +55,7 @@ const currentYaoyiyao = ref(imageUrls.yaoyiyao)
const
token
=
ref
(
wechat
?.
token
??
''
)
const
token
=
ref
(
wechat
?.
token
??
''
)
const
nickname
=
ref
(
wechat
?.
nickname
??
''
)
const
nickname
=
ref
(
wechat
?.
nickname
??
''
)
const
avatar
=
ref
(
wechat
?.
avatar
??
''
)
const
avatar
=
ref
(
wechat
?.
avatar
??
''
)
const
showGameRule
=
ref
(
fals
e
)
const
showGameRule
=
ref
(
tru
e
)
const
mobileStageRef
=
ref
<
InstanceType
<
typeof
MobileStage
>
|
null
>
(
null
)
const
mobileStageRef
=
ref
<
InstanceType
<
typeof
MobileStage
>
|
null
>
(
null
)
const
_offSocketMessage
=
ref
<
(()
=>
void
)
|
undefined
>
()
const
_offSocketMessage
=
ref
<
(()
=>
void
)
|
undefined
>
()
...
@@ -120,6 +123,7 @@ function showLoadingView() {
...
@@ -120,6 +123,7 @@ function showLoadingView() {
stopGameCountdown
()
stopGameCountdown
()
currentView
.
value
=
'loading'
currentView
.
value
=
'loading'
setDivDescVisible
(
false
)
setDivDescVisible
(
false
)
alert
(
'管理员关闭了该房间'
)
}
}
function
resetToLoadingView
()
{
function
resetToLoadingView
()
{
...
@@ -155,13 +159,13 @@ function replayGame() {
...
@@ -155,13 +159,13 @@ function replayGame() {
function
backToWaiting
()
{
function
backToWaiting
()
{
resetToLoadingView
()
resetToLoadingView
()
joinSharedRoom
(
nickname
.
value
,
token
.
value
,
avatar
.
value
)
joinSharedRoom
(
nickname
.
value
,
token
.
value
,
avatar
.
value
,
gameId
)
}
}
function
handleRoomBack
()
{
function
handleRoomBack
()
{
resetToLoadingView
()
resetToLoadingView
()
window
.
setTimeout
(()
=>
{
window
.
setTimeout
(()
=>
{
joinSharedRoom
(
nickname
.
value
,
token
.
value
,
avatar
.
value
)
joinSharedRoom
(
nickname
.
value
,
token
.
value
,
avatar
.
value
,
gameId
)
},
200
)
},
200
)
}
}
...
@@ -175,14 +179,15 @@ const showGameRuleHandler = () => {
...
@@ -175,14 +179,15 @@ const showGameRuleHandler = () => {
}
}
if
(
wechat
)
{
if
(
wechat
)
{
const
{
offSocketMessage
}
=
useGameSocket
({
const
{
offSocketMessage
}
=
useGameSocket
({
gameId
:
'game4'
,
gameId
,
auth
:
{
auth
:
{
userid
:
wechat
.
token
,
userid
:
wechat
.
token
,
},
},
onConnect
:
()
=>
{
onConnect
:
()
=>
{
window
.
setTimeout
(()
=>
{
window
.
setTimeout
(()
=>
{
joinSharedRoom
(
nickname
.
value
,
token
.
value
,
avatar
.
value
)
joinSharedRoom
(
nickname
.
value
,
token
.
value
,
avatar
.
value
,
gameId
)
},
200
)
},
200
)
},
},
onGameStart
:
async
()
=>
{
onGameStart
:
async
()
=>
{
...
@@ -224,8 +229,7 @@ onBeforeUnmount(() => {
...
@@ -224,8 +229,7 @@ onBeforeUnmount(() => {
</
script
>
</
script
>
<
template
>
<
template
>
<MobileStage
v-if=
"token"
:showGameRule=
"showGameRule"
ref=
"mobileStageRef"
<MobileStage
v-if=
"token"
:showGameRule=
"showGameRule"
ref=
"mobileStageRef"
:background=
"stageBackground"
>
:background=
"stageBackground"
>
<template
#
gameRule
>
<template
#
gameRule
>
<div
class=
"rule-container"
>
<div
class=
"rule-container"
>
<div
class=
"rule-txt-container"
>
<div
class=
"rule-txt-container"
>
...
@@ -239,9 +243,7 @@ onBeforeUnmount(() => {
...
@@ -239,9 +243,7 @@ onBeforeUnmount(() => {
5. 禁止外挂作弊,违规账号取消成绩与领奖资格;
<br
/><br
/>
5. 禁止外挂作弊,违规账号取消成绩与领奖资格;
<br
/><br
/>
祝您游戏愉快!
祝您游戏愉快!
</div>
</div>
</div>
<div
class=
"rule-close"
@
click=
"showGameRuleHandler"
></div>
<div
class=
"rule-close"
>
<div
@
click=
"showGameRuleHandler"
></div>
</div>
</div>
</div>
</div>
</
template
>
</
template
>
...
@@ -261,42 +263,36 @@ onBeforeUnmount(() => {
...
@@ -261,42 +263,36 @@ onBeforeUnmount(() => {
<
style
scoped
>
<
style
scoped
>
.rule-container
{
.rule-container
{
.rule-txt-container
{
.rule-txt-container
{
width
:
62vw
;
background
:
v-bind
(
'imageUrls.rule'
)
center
/
cover
no-repeat
;
margin
:
0
40px
;
width
:
692px
;
border-radius
:
5px
;
height
:
797px
;
background
:
#FFF9E4
;
transform
:
scale
(
0.5
);
padding-top
:
20px
;
padding-bottom
:
10px
;
.rule-title
{
.rule-title
{
text-align
:
center
;
text-align
:
center
;
color
:
#850000
;
color
:
white
;
font-weight
:
bold
;
font-weight
:
bold
;
font-size
:
15pt
;
font-size
:
22pt
;
margin-top
:
10px
;
letter-spacing
:
4px
;
}
}
.rule-txt
{
.rule-txt
{
font-size
:
12
pt
;
font-size
:
26
pt
;
padding
:
1
0px
;
padding
:
4
0px
;
margin-top
:
10px
;
margin-top
:
10px
;
color
:
#AA0000
;
}
}
}
}
.rule-close
{
.rule-close
{
width
:
32px
;
width
:
57px
;
height
:
130px
;
height
:
57px
;
margin
:
0
auto
;
background
:
v-bind
(
'imageUrls.close'
)
center
/
cover
no-repeat
;
background
:
v-bind
(
'imageUrls.close'
)
center
/
cover
;
transform
:
translateX
(
-50%
)
scale
(
1.4
);
position
:
relative
;
>div
{
position
:
absolute
;
position
:
absolute
;
bottom
:
0
;
bottom
:
-75px
;
width
:
32px
;
left
:
50%
;
height
:
32px
;
border-radius
:
16px
;
}
}
}
}
}
</
style
>
</
style
>
frontend-h5/src/pages/game5/Game5.vue
View file @
a8efe97a
...
@@ -9,6 +9,7 @@ import ScoreView from './views/ScoreView.vue'
...
@@ -9,6 +9,7 @@ import ScoreView from './views/ScoreView.vue'
import
{
$getWechat
}
from
'@/commons/utils.ts'
import
{
$getWechat
}
from
'@/commons/utils.ts'
import
{
playGame1Music
}
from
'@/commons/music'
import
{
playGame1Music
}
from
'@/commons/music'
const
gameId
=
'game5'
;
type
GameView
=
'loading'
|
'playing'
|
'score'
type
GameView
=
'loading'
|
'playing'
|
'score'
type
RankPlayer
=
{
type
RankPlayer
=
{
rank
:
number
rank
:
number
...
@@ -63,7 +64,7 @@ const isGuPlaying = ref(false)
...
@@ -63,7 +64,7 @@ const isGuPlaying = ref(false)
const
token
=
ref
(
wechat
?.
token
??
''
)
const
token
=
ref
(
wechat
?.
token
??
''
)
const
nickname
=
ref
(
wechat
?.
nickname
??
''
)
const
nickname
=
ref
(
wechat
?.
nickname
??
''
)
const
avatar
=
ref
(
wechat
?.
avatar
??
''
)
const
avatar
=
ref
(
wechat
?.
avatar
??
''
)
const
showGameRule
=
ref
(
fals
e
)
const
showGameRule
=
ref
(
tru
e
)
const
showGameRank
=
ref
(
false
)
const
showGameRank
=
ref
(
false
)
const
rankList
=
ref
<
RankPlayer
[]
>
([])
const
rankList
=
ref
<
RankPlayer
[]
>
([])
const
displayRankList
=
computed
<
RankPlayer
[]
>
(()
=>
{
const
displayRankList
=
computed
<
RankPlayer
[]
>
(()
=>
{
...
@@ -149,6 +150,7 @@ function showLoadingView() {
...
@@ -149,6 +150,7 @@ function showLoadingView() {
stopGameCountdown
()
stopGameCountdown
()
currentView
.
value
=
'loading'
currentView
.
value
=
'loading'
setDivDescVisible
(
false
)
setDivDescVisible
(
false
)
alert
(
'管理员关闭了该房间'
)
}
}
function
resetToLoadingView
()
{
function
resetToLoadingView
()
{
...
@@ -191,7 +193,7 @@ function showGameOverRank() {
...
@@ -191,7 +193,7 @@ function showGameOverRank() {
function
handleRoomBack
()
{
function
handleRoomBack
()
{
resetToLoadingView
()
resetToLoadingView
()
window
.
setTimeout
(()
=>
{
window
.
setTimeout
(()
=>
{
joinSharedRoom
(
nickname
.
value
,
token
.
value
,
avatar
.
value
)
joinSharedRoom
(
nickname
.
value
,
token
.
value
,
avatar
.
value
,
gameId
)
},
200
)
},
200
)
}
}
...
@@ -210,7 +212,7 @@ if (wechat) {
...
@@ -210,7 +212,7 @@ if (wechat) {
},
},
onConnect
:
()
=>
{
onConnect
:
()
=>
{
window
.
setTimeout
(()
=>
{
window
.
setTimeout
(()
=>
{
const
joined
=
joinSharedRoom
(
nickname
.
value
,
token
.
value
,
avatar
.
value
)
const
joined
=
joinSharedRoom
(
nickname
.
value
,
token
.
value
,
avatar
.
value
,
gameId
)
},
200
)
},
200
)
},
},
onGameStart
:
async
()
=>
{
onGameStart
:
async
()
=>
{
...
@@ -325,9 +327,9 @@ const rankCloseHandler = () => {
...
@@ -325,9 +327,9 @@ const rankCloseHandler = () => {
4.禁止外挂作弊,违规账号取消成绩与领奖资格;
<br
/><br
/>
4.禁止外挂作弊,违规账号取消成绩与领奖资格;
<br
/><br
/>
祝您游戏愉快!
祝您游戏愉快!
</div>
</div>
</div>
<div
class=
"rule-close"
@
click=
"showGameRuleHandler"
></div>
<div
class=
"rule-close"
@
click=
"showGameRuleHandler"
></div>
</div>
</div>
</div>
</
template
>
</
template
>
<LoadingView
v-if=
"currentView === 'loading'"
:image-urls=
"imageUrls"
:user-join-status=
"userJoinStatus"
<LoadingView
v-if=
"currentView === 'loading'"
:image-urls=
"imageUrls"
:user-join-status=
"userJoinStatus"
@
touchGameRule=
"showGameRuleHandler"
/>
@
touchGameRule=
"showGameRuleHandler"
/>
...
@@ -344,12 +346,9 @@ const rankCloseHandler = () => {
...
@@ -344,12 +346,9 @@ const rankCloseHandler = () => {
<
style
scoped
>
<
style
scoped
>
.rule-container
{
.rule-container
{
.rule-txt-container
{
.rule-txt-container
{
position
:
absolute
;
background
:
v-bind
(
'imageUrls.rule'
)
center
/
cover
no-repeat
;
background
:
v-bind
(
'imageUrls.rule'
)
center
/
cover
no-repeat
;
width
:
692px
;
width
:
692px
;
height
:
797px
;
height
:
797px
;
left
:
-157px
;
top
:
-75px
;
transform
:
scale
(
0.5
);
transform
:
scale
(
0.5
);
.rule-title
{
.rule-title
{
...
@@ -372,11 +371,11 @@ const rankCloseHandler = () => {
...
@@ -372,11 +371,11 @@ const rankCloseHandler = () => {
.rule-close
{
.rule-close
{
width
:
57px
;
width
:
57px
;
height
:
57px
;
height
:
57px
;
margin
:
0
auto
;
background
:
v-bind
(
'imageUrls.close'
)
center
/
cover
no-repeat
;
margin-top
:
450px
;
transform
:
translateX
(
-50%
)
scale
(
1.4
)
;
background
:
v-bind
(
'imageUrls.close'
)
center
/
cover
;
position
:
absolute
;
position
:
relative
;
bottom
:
-75px
;
transform
:
scale
(
0.8
)
;
left
:
50%
;
}
}
}
}
...
...
frontend-h5/src/pages/game5/views/LoadingView.vue
View file @
a8efe97a
...
@@ -145,6 +145,7 @@ onMounted(() => {
...
@@ -145,6 +145,7 @@ onMounted(() => {
height
:
126px
;
height
:
126px
;
color
:
white
;
color
:
white
;
position
:
absolute
;
position
:
absolute
;
z-index
:
-1
;
top
:
786px
;
top
:
786px
;
left
:
50%
;
left
:
50%
;
transform
:
translate
(
-50%
);
transform
:
translate
(
-50%
);
...
...
frontend-h5/src/pages/game6/Game.vue
View file @
a8efe97a
...
@@ -57,13 +57,20 @@ const displayRankList = computed<RankPlayer[]>(() => {
...
@@ -57,13 +57,20 @@ const displayRankList = computed<RankPlayer[]>(() => {
}
}
})
})
})
})
const
rankScore
=
computed
<
number
|
string
>
(()
=>
{
const
currentPlayer
=
rankList
.
value
.
slice
(
0
,
10
)
.
find
(
item
=>
item
.
rank
===
rank
.
value
)
return
currentPlayer
?.
score
??
score
.
value
})
// const guFrames: [string, string, string] = [imageUrls.gu01, imageUrls.gu02, imageUrls.gu03]
// const guFrames: [string, string, string] = [imageUrls.gu01, imageUrls.gu02, imageUrls.gu03]
// const currentGu = ref(imageUrls.gu01)
// const currentGu = ref(imageUrls.gu01)
const
isGuPlaying
=
ref
(
false
)
const
isGuPlaying
=
ref
(
false
)
const
token
=
ref
(
wechat
?.
token
??
''
)
const
token
=
ref
(
wechat
?.
token
??
''
)
const
nickname
=
ref
(
wechat
?.
nickname
??
''
)
const
nickname
=
ref
(
wechat
?.
nickname
??
''
)
const
avatar
=
ref
(
wechat
?.
avatar
??
''
)
const
avatar
=
ref
(
wechat
?.
avatar
??
''
)
const
showGameRule
=
ref
(
fals
e
)
const
showGameRule
=
ref
(
tru
e
)
const
showGameRank
=
ref
(
false
)
const
showGameRank
=
ref
(
false
)
const
mobileStageRef
=
ref
<
InstanceType
<
typeof
MobileStage
>
|
null
>
(
null
)
const
mobileStageRef
=
ref
<
InstanceType
<
typeof
MobileStage
>
|
null
>
(
null
)
...
@@ -297,9 +304,9 @@ const rankCloseHandler = () => {
...
@@ -297,9 +304,9 @@ const rankCloseHandler = () => {
4. 禁止外挂作弊,违规账号取消成绩与领奖资格;
<br
/><br
/>
4. 禁止外挂作弊,违规账号取消成绩与领奖资格;
<br
/><br
/>
祝您游戏愉快!
祝您游戏愉快!
</div>
</div>
</div>
<div
class=
"rule-close"
@
click=
"showGameRuleHandler"
></div>
<div
class=
"rule-close"
@
click=
"showGameRuleHandler"
></div>
</div>
</div>
</div>
</
template
>
</
template
>
<
template
#
gameRank
>
<
template
#
gameRank
>
<div
class=
"ranklist-container"
>
<div
class=
"ranklist-container"
>
...
@@ -330,7 +337,7 @@ const rankCloseHandler = () => {
...
@@ -330,7 +337,7 @@ const rankCloseHandler = () => {
<div
class=
"avatar"
:style=
"
{ backgroundImage: `url(${avatar})` }">
</div>
<div
class=
"avatar"
:style=
"
{ backgroundImage: `url(${avatar})` }">
</div>
<div>
{{
nickname
}}
</div>
<div>
{{
nickname
}}
</div>
</div>
</div>
<div
class=
"col-3"
>
{{
s
core
}}
</div>
<div
class=
"col-3"
>
{{
rankS
core
}}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
...
@@ -348,12 +355,9 @@ const rankCloseHandler = () => {
...
@@ -348,12 +355,9 @@ const rankCloseHandler = () => {
<
style
scoped
>
<
style
scoped
>
.rule-container
{
.rule-container
{
.rule-txt-container
{
.rule-txt-container
{
position
:
absolute
;
background
:
v-bind
(
'imageUrls.rule'
)
center
/
cover
no-repeat
;
background
:
v-bind
(
'imageUrls.rule'
)
center
/
cover
no-repeat
;
width
:
692px
;
width
:
692px
;
height
:
797px
;
height
:
797px
;
left
:
-157px
;
top
:
-75px
;
transform
:
scale
(
0.5
);
transform
:
scale
(
0.5
);
.rule-title
{
.rule-title
{
...
@@ -376,11 +380,11 @@ const rankCloseHandler = () => {
...
@@ -376,11 +380,11 @@ const rankCloseHandler = () => {
.rule-close
{
.rule-close
{
width
:
57px
;
width
:
57px
;
height
:
57px
;
height
:
57px
;
margin
:
0
auto
;
background
:
v-bind
(
'imageUrls.close'
)
center
/
cover
no-repeat
;
margin-top
:
450px
;
transform
:
translateX
(
-50%
)
scale
(
1.4
)
;
background
:
v-bind
(
'imageUrls.close'
)
center
/
cover
;
position
:
absolute
;
position
:
relative
;
bottom
:
-75px
;
transform
:
scale
(
0.8
)
;
left
:
50%
;
}
}
}
}
...
...
frontend-h5/src/pages/game6/views/LoadingView.vue
View file @
a8efe97a
...
@@ -77,7 +77,7 @@ onMounted(() => {
...
@@ -77,7 +77,7 @@ onMounted(() => {
.game-desc
{
.game-desc
{
position
:
absolute
;
position
:
absolute
;
z-index
:
2
;
z-index
:
9999999999
;
top
:
50%
;
top
:
50%
;
left
:
var
(
--stage-viewport-left
,
0
);
left
:
var
(
--stage-viewport-left
,
0
);
display
:
flex
;
display
:
flex
;
...
...
frontend-h5/vite.config.ts
View file @
a8efe97a
...
@@ -26,7 +26,7 @@ function copyImageAssets() {
...
@@ -26,7 +26,7 @@ function copyImageAssets() {
}
}
export
default
defineConfig
(({
command
})
=>
({
export
default
defineConfig
(({
command
})
=>
({
base
:
command
===
'build'
?
'/
cc/
h5/'
:
'/'
,
base
:
command
===
'build'
?
'/h5/'
:
'/'
,
define
:
{
define
:
{
__APP_DOMAIN__
:
JSON
.
stringify
(
command
===
'build'
?
buildDomain
:
''
),
__APP_DOMAIN__
:
JSON
.
stringify
(
command
===
'build'
?
buildDomain
:
''
),
__DEBUG__
:
JSON
.
stringify
(
command
===
'serve'
),
__DEBUG__
:
JSON
.
stringify
(
command
===
'serve'
),
...
...
frontend-large/src/assets/images/applause.mp3
0 → 100644
View file @
a8efe97a
File added
frontend-large/src/assets/images/game1.mp3
View file @
a8efe97a
No preview for this file type
frontend-large/src/commons/music.ts
View file @
a8efe97a
import
game1MusicUrl
from
'@/assets/images/game1.mp3'
import
game1MusicUrl
from
'@/assets/images/game1.mp3'
import
game4MusicUrl
from
'@/assets/images/game1.mp3'
// 需要改成正式的路径
import
game5MusicUrl
from
'@/assets/images/game1.mp3'
// 需要改成正式的路径
import
game6MusicUrl
from
'@/assets/images/game6.mp3'
import
game6MusicUrl
from
'@/assets/images/game6.mp3'
import
go321
from
'@/assets/images/321go.mp3'
import
go321
from
'@/assets/images/321go.mp3'
import
applause
from
'@/assets/images/applause.mp3'
let
backgroundMusic
:
HTMLAudioElement
|
null
=
null
let
backgroundMusic
:
HTMLAudioElement
|
null
=
null
let
countdownTemplate
:
HTMLAudioElement
|
null
=
null
let
countdownTemplate
:
HTMLAudioElement
|
null
=
null
let
pendingCountdownRetry
:
(()
=>
void
)
|
null
=
null
let
pendingCountdownRetry
:
(()
=>
void
)
|
null
=
null
const
countdownAudios
=
new
Set
<
HTMLAudioElement
>
()
const
countdownAudios
=
new
Set
<
HTMLAudioElement
>
()
function
getBackgroundMusic
(
music
:
string
)
{
export
function
stopAllMusic
()
{
stopApplauseMusic
();
stopGame1Music
();
// stopGame2Music();
// stopGame3Music();
stopGame4Music
();
stopGame5Music
();
stopGame6Music
();
backgroundMusic
=
null
;
}
function
getBackgroundMusic
(
music
:
string
,
force
:
boolean
=
true
)
{
if
(
force
)
{
//
if
(
backgroundMusic
)
{
stopApplauseMusic
();
stopGame1Music
();
// stopGame2Music();
// stopGame3Music();
stopGame4Music
();
stopGame5Music
();
stopGame6Music
();
backgroundMusic
=
null
;
}
}
if
(
!
backgroundMusic
)
{
if
(
!
backgroundMusic
)
{
backgroundMusic
=
new
Audio
(
music
)
backgroundMusic
=
new
Audio
(
music
)
backgroundMusic
.
loop
=
true
backgroundMusic
.
loop
=
true
...
@@ -19,6 +47,26 @@ function getBackgroundMusic(music: string) {
...
@@ -19,6 +47,26 @@ function getBackgroundMusic(music: string) {
return
backgroundMusic
return
backgroundMusic
}
}
export
async
function
playApplauseMusic
()
{
const
audio
=
getBackgroundMusic
(
applause
)
try
{
await
audio
.
play
()
window
.
removeEventListener
(
'pointerdown'
,
playApplauseMusic
)
window
.
removeEventListener
(
'keydown'
,
playApplauseMusic
)
}
catch
{
window
.
addEventListener
(
'pointerdown'
,
playApplauseMusic
,
{
once
:
false
})
window
.
addEventListener
(
'keydown'
,
playApplauseMusic
,
{
once
:
false
})
}
}
export
function
stopApplauseMusic
()
{
window
.
removeEventListener
(
'pointerdown'
,
playApplauseMusic
)
window
.
removeEventListener
(
'keydown'
,
playApplauseMusic
)
backgroundMusic
?.
pause
()
}
export
async
function
playGame1Music
()
{
export
async
function
playGame1Music
()
{
const
audio
=
getBackgroundMusic
(
game1MusicUrl
)
const
audio
=
getBackgroundMusic
(
game1MusicUrl
)
...
@@ -38,6 +86,45 @@ export function stopGame1Music() {
...
@@ -38,6 +86,45 @@ export function stopGame1Music() {
backgroundMusic
?.
pause
()
backgroundMusic
?.
pause
()
}
}
export
async
function
playGame4Music
()
{
const
audio
=
getBackgroundMusic
(
game4MusicUrl
)
try
{
await
audio
.
play
()
window
.
removeEventListener
(
'pointerdown'
,
playGame4Music
)
window
.
removeEventListener
(
'keydown'
,
playGame4Music
)
}
catch
{
window
.
addEventListener
(
'pointerdown'
,
playGame4Music
,
{
once
:
true
})
window
.
addEventListener
(
'keydown'
,
playGame4Music
,
{
once
:
true
})
}
}
export
function
stopGame4Music
()
{
window
.
removeEventListener
(
'pointerdown'
,
playGame4Music
)
window
.
removeEventListener
(
'keydown'
,
playGame4Music
)
backgroundMusic
?.
pause
()
}
export
async
function
playGame5Music
()
{
const
audio
=
getBackgroundMusic
(
game4MusicUrl
)
try
{
await
audio
.
play
()
window
.
removeEventListener
(
'pointerdown'
,
playGame5Music
)
window
.
removeEventListener
(
'keydown'
,
playGame5Music
)
}
catch
{
window
.
addEventListener
(
'pointerdown'
,
playGame5Music
,
{
once
:
true
})
window
.
addEventListener
(
'keydown'
,
playGame5Music
,
{
once
:
true
})
}
}
export
function
stopGame5Music
()
{
window
.
removeEventListener
(
'pointerdown'
,
playGame5Music
)
window
.
removeEventListener
(
'keydown'
,
playGame5Music
)
backgroundMusic
?.
pause
()
}
export
async
function
playGame6Music
()
{
export
async
function
playGame6Music
()
{
const
audio
=
getBackgroundMusic
(
game6MusicUrl
)
const
audio
=
getBackgroundMusic
(
game6MusicUrl
)
...
...
frontend-large/src/commons/ws.ts
View file @
a8efe97a
...
@@ -57,7 +57,7 @@ export function initSocket(args: SocketInitArgs): Socket | null {
...
@@ -57,7 +57,7 @@ export function initSocket(args: SocketInitArgs): Socket | null {
socket
.
onAny
((
evt
,
payload
)
=>
{
socket
.
onAny
((
evt
,
payload
)
=>
{
const
data
=
decode
(
payload
);
const
data
=
decode
(
payload
);
if
(
$is_run_local
())
{
if
(
$is_run_local
())
{
console
.
log
(
evt
,
data
);
console
.
log
(
"recv<============"
,
evt
,
data
);
}
}
messageHandlers
.
forEach
((
handler
)
=>
handler
(
evt
,
data
));
messageHandlers
.
forEach
((
handler
)
=>
handler
(
evt
,
data
));
});
});
...
@@ -78,7 +78,7 @@ export function sendSocketMessage(cmd: string, data: any = {}): boolean {
...
@@ -78,7 +78,7 @@ export function sendSocketMessage(cmd: string, data: any = {}): boolean {
return
false
;
return
false
;
}
}
if
(
$is_run_local
())
{
if
(
$is_run_local
())
{
console
.
log
(
'================
===
>send'
,
cmd
,
data
);
console
.
log
(
'================>send'
,
cmd
,
data
);
}
}
socket
.
send
(
encode
({
cmd
,
data
}));
socket
.
send
(
encode
({
cmd
,
data
}));
return
true
;
return
true
;
...
...
frontend-large/src/composables/useAdminGameSocket.ts
View file @
a8efe97a
import
CryptoJS
from
'crypto-js'
import
CryptoJS
from
'crypto-js'
import
{
onBeforeUnmount
,
onMounted
}
from
'vue'
import
{
onBeforeUnmount
,
onMounted
}
from
'vue'
import
{
$read_socket_storge
}
from
'@/commons/utils'
import
{
$read_socket_storge
,
$remove_socket_storage
}
from
'@/commons/utils'
import
{
initSocket
,
onSocketMessage
,
sendSocketMessage
}
from
'@/commons/ws'
import
{
initSocket
,
onSocketMessage
,
sendSocketMessage
}
from
'@/commons/ws'
import
router
from
'@/router'
type
SocketPayload
=
{
type
SocketPayload
=
{
msg
?:
string
msg
?:
string
...
@@ -10,13 +11,14 @@ type SocketPayload = {
...
@@ -10,13 +11,14 @@ type SocketPayload = {
}
}
type
AdminGameSocketOptions
=
{
type
AdminGameSocketOptions
=
{
gameId
:
string
gameId
?:
string
,
loginRedirectPath
?:
string
loginRedirectPath
?:
string
onRoomState
?:
(
data
:
any
)
=>
void
onRoomState
?:
(
data
:
any
)
=>
void
onRoomJoin
?:
(
data
:
any
)
=>
void
onRoomJoin
?:
(
data
:
any
)
=>
void
onGameStart
?:
(
data
:
any
)
=>
void
|
Promise
<
void
>
onGameStart
?:
(
data
:
any
)
=>
void
|
Promise
<
void
>
onRoomRank
?:
(
data
:
any
)
=>
void
onRoomRank
?:
(
data
:
any
)
=>
void
onRelogin
?:
()
=>
void
onRelogin
?:
()
=>
void
onAny
?:
(
evt
:
string
,
data
:
any
)
=>
void
}
}
export
function
useAdminGameSocket
(
options
:
AdminGameSocketOptions
)
{
export
function
useAdminGameSocket
(
options
:
AdminGameSocketOptions
)
{
...
@@ -41,13 +43,13 @@ export function useAdminGameSocket(options: AdminGameSocketOptions) {
...
@@ -41,13 +43,13 @@ export function useAdminGameSocket(options: AdminGameSocketOptions) {
return
sendSocketMessage
(
cmd
,
data
)
return
sendSocketMessage
(
cmd
,
data
)
}
}
function
closeRoom
(){
function
closeRoom
()
{
return
sendSocketMessage
(
'room_close'
,
{})
return
sendSocketMessage
(
'room_close'
,
{})
}
}
onMounted
(()
=>
{
onMounted
(()
=>
{
const
{
passphrase
,
token
,
socket_path
,
client_ns
,
domain
}
=
$read_socket_storge
()
const
{
passphrase
,
token
,
socket_path
,
client_ns
,
domain
}
=
$read_socket_storge
()
initSocket
({
let
socket
=
initSocket
({
socket_path
:
`
${
domain
}${
socket_path
}
`
,
socket_path
:
`
${
domain
}${
socket_path
}
`
,
client_ns
,
client_ns
,
auth
:
{
auth
:
{
...
@@ -67,33 +69,51 @@ export function useAdminGameSocket(options: AdminGameSocketOptions) {
...
@@ -67,33 +69,51 @@ export function useAdminGameSocket(options: AdminGameSocketOptions) {
// }
// }
if
(
evt
==
'login_result'
)
{
if
(
evt
==
'login_result'
)
{
alert
(
msg
)
alert
(
msg
)
options
.
onRelogin
?.()
// options.onRelogin?.()
socket
?.
close
();
$remove_socket_storage
();
await
router
.
replace
(
`/login`
);
location
.
href
=
location
.
href
;
return
;
}
else
if
(
evt
==
'new_admin_result'
)
{
alert
(
msg
);
socket
?.
close
();
$remove_socket_storage
();
await
router
.
replace
(
`/login`
);
location
.
href
=
location
.
href
;
return
;
return
;
}
}
alert
(
msg
)
return
}
}
switch
(
evt
)
{
switch
(
evt
)
{
case
'room_state_result'
:
{
case
'room_state_result'
:
{
if
(
data
.
gameId
)
{
//如果这两个值不一致说明浏览器有直接更新游戏房间号
if
(
data
.
gameId
!=
options
.
gameId
)
{
location
.
reload
();
return
;
}
}
options
.
onRoomState
?.(
data
)
options
.
onRoomState
?.(
data
)
break
return
}
}
case
'room_join_result'
:
{
case
'room_join_result'
:
{
options
.
onRoomJoin
?.(
data
)
options
.
onRoomJoin
?.(
data
)
break
return
}
}
case
'game_start_result'
:
{
case
'game_start_result'
:
{
if
(
data
===
options
.
gameId
)
{
if
(
data
===
options
.
gameId
)
{
await
options
.
onGameStart
?.(
data
)
await
options
.
onGameStart
?.(
data
)
}
}
break
return
}
}
case
'room_rank_result'
:
{
case
'room_rank_result'
:
{
options
.
onRoomRank
?.(
data
)
options
.
onRoomRank
?.(
data
)
break
return
}
}
}
}
options
?.
onAny
?.(
evt
,
payload
);
})
})
})
})
...
...
frontend-large/src/
component
s/Login.vue
→
frontend-large/src/
page
s/Login.vue
View file @
a8efe97a
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
cssAssetUrl
}
from
'@/commons/assets'
;
import
{
$save
}
from
'@/commons/utils.ts'
;
import
{
$save
}
from
'@/commons/utils.ts'
;
import
{
onMounted
,
ref
}
from
'vue'
import
{
onMounted
,
ref
}
from
'vue'
import
{
useRouter
}
from
'vue-router'
import
{
useRouter
}
from
'vue-router'
const
emit
=
defineEmits
<
{
loginSuccess
:
[]
}
>
()
const
router
=
useRouter
()
const
router
=
useRouter
()
const
username
=
ref
(
''
)
const
username
=
ref
(
''
)
const
password
=
ref
(
''
)
const
password
=
ref
(
''
)
const
imageUrls
=
{
bg1
:
cssAssetUrl
(
'main-bg1.png'
),
logo
:
cssAssetUrl
(
'game1/logo.png'
),
title1
:
cssAssetUrl
(
'main-title.png'
),
}
async
function
login
()
{
async
function
login
()
{
let
domain
=
localStorage
.
getItem
(
'domain'
)
||
''
;
let
domain
=
localStorage
.
getItem
(
'domain'
)
||
''
;
const
res
=
await
fetch
(
`
${
domain
}
/manager/login`
,
{
const
res
=
await
fetch
(
`
${
domain
}
/manager/login`
,
{
...
@@ -22,11 +25,10 @@ async function login() {
...
@@ -22,11 +25,10 @@ async function login() {
})
})
const
data
=
await
res
.
json
()
const
data
=
await
res
.
json
()
if
(
!
res
.
ok
||
data
.
state
!==
1
)
{
// if (!res.ok || data.state !== 1) {
alert
(
data
.
msg
||
'Login failed'
)
// alert(data.msg || 'Login failed')
throw
new
Error
(
data
.
msg
||
'Login failed'
)
// throw new Error(data.msg || 'Login failed')
}
// }
return
data
return
data
}
}
...
@@ -40,7 +42,8 @@ const loginHandler = async () => {
...
@@ -40,7 +42,8 @@ const loginHandler = async () => {
for
(
let
i
in
data
)
{
for
(
let
i
in
data
)
{
$save
(
i
,
data
[
i
]);
$save
(
i
,
data
[
i
]);
}
}
emit
(
'loginSuccess'
);
alert
(
'登录成功'
)
await
router
.
replace
(
`/main`
);
}
}
onMounted
(()
=>
{
onMounted
(()
=>
{
...
@@ -48,6 +51,9 @@ onMounted(() => {
...
@@ -48,6 +51,9 @@ onMounted(() => {
</
script
>
</
script
>
<
template
>
<
template
>
<div
class=
"bg"
>
<div
class=
"img-logo"
></div>
<div
class=
"img-title1"
></div>
<div
class=
"login-page"
>
<div
class=
"login-page"
>
<form
class=
"login-panel"
@
submit
.
prevent=
"loginHandler"
>
<form
class=
"login-panel"
@
submit
.
prevent=
"loginHandler"
>
<div
class=
"panel-header"
>
<div
class=
"panel-header"
>
...
@@ -67,9 +73,40 @@ onMounted(() => {
...
@@ -67,9 +73,40 @@ onMounted(() => {
<button
class=
"login-button"
type=
"submit"
>
登录
</button>
<button
class=
"login-button"
type=
"submit"
>
登录
</button>
</form>
</form>
</div>
</div>
</div>
</
template
>
</
template
>
<
style
scoped
>
<
style
scoped
>
.bg
{
width
:
1920px
;
height
:
1080px
;
background
:
v-bind
(
'imageUrls.bg1'
)
center
/
cover
no-repeat
;
display
:
flex
;
flex-direction
:
column
;
overflow
:
hidden
;
position
:
relative
;
.img-logo
{
background
:
v-bind
(
'imageUrls.logo'
);
background-size
:
cover
;
width
:
428px
;
height
:
77px
;
position
:
absolute
;
left
:
37px
;
top
:
82px
;
}
.img-title1
{
background
:
v-bind
(
'imageUrls.title1'
)
center
/
cover
no-repeat
;
width
:
1024px
;
height
:
143px
;
margin
:
0
auto
;
position
:
relative
;
top
:
50px
;
}
}
.login-page
{
.login-page
{
position
:
absolute
;
position
:
absolute
;
z-index
:
1
;
z-index
:
1
;
...
@@ -79,7 +116,6 @@ onMounted(() => {
...
@@ -79,7 +116,6 @@ onMounted(() => {
align-items
:
center
;
align-items
:
center
;
justify-content
:
center
;
justify-content
:
center
;
overflow
:
hidden
;
overflow
:
hidden
;
background
:
rgba
(
0
,
0
,
0
,
0.8
);
}
}
.login-panel
{
.login-panel
{
...
...
frontend-large/src/pages/Main.vue
View file @
a8efe97a
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
cssAssetUrl
}
from
'@/commons/assets.ts'
;
import
{
cssAssetUrl
}
from
'@/commons/assets.ts'
;
import
{
$read
}
from
'@/commons/utils'
;
import
{
$read
}
from
'@/commons/utils'
;
import
{
useAdminGameSocket
}
from
'@/composables/useAdminGameSocket'
;
import
router
from
'@/router'
;
import
router
from
'@/router'
;
import
{
ref
}
from
'vue'
;
import
{
onMounted
,
onUnmounted
,
ref
}
from
'vue'
;
import
Login
from
'../components/Login.vue'
;
const
imageUrls
=
{
const
imageUrls
=
{
bg1
:
cssAssetUrl
(
'main-bg1.png'
),
bg1
:
cssAssetUrl
(
'main-bg1.png'
),
...
@@ -45,10 +45,27 @@ const loginSuccessHandler = () => {
...
@@ -45,10 +45,27 @@ const loginSuccessHandler = () => {
show_login
.
value
=
false
;
show_login
.
value
=
false
;
gameHandler
(
item_index
.
value
);
gameHandler
(
item_index
.
value
);
}
}
const
confirmRefresh
=
(
event
:
BeforeUnloadEvent
)
=>
{
event
.
preventDefault
()
event
.
returnValue
=
''
}
useAdminGameSocket
({})
onMounted
(()
=>
{
window
.
addEventListener
(
'beforeunload'
,
confirmRefresh
)
})
onUnmounted
(()
=>
{
window
.
removeEventListener
(
'beforeunload'
,
confirmRefresh
)
})
</
script
>
</
script
>
<
template
>
<
template
>
<
Login
v-if=
"show_login"
@
loginSuccess=
"loginSuccessHandler"
/
>
<
!--
<Login
v-if=
"show_login"
@
loginSuccess=
"loginSuccessHandler"
/>
--
>
<div
class=
"bg"
>
<div
class=
"bg"
>
<div
class=
"img-logo"
></div>
<div
class=
"img-logo"
></div>
<div
class=
"img-title1"
></div>
<div
class=
"img-title1"
></div>
...
...
frontend-large/src/pages/game1/Game.vue
View file @
a8efe97a
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
nextTick
,
onMounted
,
onUnmounted
,
ref
}
from
'vue'
import
{
nextTick
,
onMounted
,
onUnmounted
,
ref
,
watch
}
from
'vue'
import
{
useRouter
}
from
'vue-router'
import
{
useRouter
}
from
'vue-router'
import
Loading
from
'./views/LoadingView.vue'
import
Loading
from
'./views/LoadingView.vue'
import
Rank1
from
'./views/Rank1View.vue'
import
Rank1
from
'./views/Rank1View.vue'
import
Rank2
from
'./views/Rank2View.vue'
import
Rank2
from
'./views/Rank2View.vue'
import
{
useAdminGameSocket
}
from
'@/composables/useAdminGameSocket'
import
{
useAdminGameSocket
}
from
'@/composables/useAdminGameSocket'
import
type
Player
from
'@/commons/player.ts'
import
type
Player
from
'@/commons/player.ts'
import
{
play
Game1
Music
,
stopGame1Music
}
from
'@/commons/music'
import
{
play
ApplauseMusic
,
playGame1Music
,
stopAll
Music
,
stopGame1Music
}
from
'@/commons/music'
import
{
$remove_socket_storage
}
from
'@/commons/utils.ts'
import
{
$remove_socket_storage
}
from
'@/commons/utils.ts'
const
router
=
useRouter
()
const
router
=
useRouter
()
...
@@ -114,17 +114,22 @@ const gotoRank1WithIntro = async () => {
...
@@ -114,17 +114,22 @@ const gotoRank1WithIntro = async () => {
isPlayingStartAnimation
=
false
isPlayingStartAnimation
=
false
}
}
function
handleRoomState
(
data
:
any
)
{
const
gameId
=
'game1'
const
{
startGame
,
createRoom
,
backRoom
,
closeRoom
}
=
useAdminGameSocket
({
gameId
,
onRoomState
:
(
data
:
any
)
=>
{
if
(
Array
.
isArray
(
data
?.
list
))
{
if
(
Array
.
isArray
(
data
?.
list
))
{
renderPlayers
(
data
)
renderPlayers
(
data
)
}
}
switch
(
data
?.
status
)
{
switch
(
data
?.
status
)
{
case
0
:
case
0
:
gotoLoading
(
true
)
gotoLoading
(
true
)
createRoom
(
1
)
createRoom
(
1
)
break
break
case
1
:
case
1
:
// if(data.gameId && data.gameId!=gameId){
// return;
// }
gotoLoading
()
gotoLoading
()
break
break
case
2
:
case
2
:
...
@@ -135,11 +140,7 @@ function handleRoomState(data: any) {
...
@@ -135,11 +140,7 @@ function handleRoomState(data: any) {
screen
.
value
=
'rank2'
screen
.
value
=
'rank2'
break
break
}
}
}
},
const
{
startGame
,
createRoom
,
backRoom
,
closeRoom
}
=
useAdminGameSocket
({
gameId
:
'game1'
,
onRoomState
:
handleRoomState
,
onRoomJoin
:
(
data
)
=>
{
onRoomJoin
:
(
data
)
=>
{
renderPlayers
(
data
)
renderPlayers
(
data
)
gotoLoading
()
gotoLoading
()
...
@@ -184,9 +185,18 @@ onMounted(() => {
...
@@ -184,9 +185,18 @@ onMounted(() => {
})
})
onUnmounted
(()
=>
{
onUnmounted
(()
=>
{
stop
Game1
Music
()
stop
All
Music
()
window
.
removeEventListener
(
'beforeunload'
,
confirmRefresh
)
window
.
removeEventListener
(
'beforeunload'
,
confirmRefresh
)
})
})
watch
(
screen
,
(
value
)
=>
{
// console.log(value);
if
(
value
==
'rank2'
){
playApplauseMusic
();
}
else
if
(
value
==
'loading'
){
playGame1Music
();
}
})
</
script
>
</
script
>
<
template
>
<
template
>
...
...
frontend-large/src/pages/game4/Game4.vue
View file @
a8efe97a
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
nextTick
,
onMounted
,
onUnmounted
,
ref
}
from
"vue"
;
import
{
nextTick
,
onMounted
,
onUnmounted
,
ref
,
watch
}
from
"vue"
;
import
{
playApplauseMusic
,
playGame4Music
,
stopAllMusic
,
stopGame4Music
}
from
'@/commons/music'
import
Loading
from
"./views/LoadingView.vue"
;
import
Loading
from
"./views/LoadingView.vue"
;
import
Rank1
from
"./views/Rank1View.vue"
;
import
Rank1
from
"./views/Rank1View.vue"
;
import
Rank2
from
"./views/Rank2View.vue"
;
import
Rank2
from
"./views/Rank2View.vue"
;
import
{
useAdminGameSocket
}
from
"@/composables/useAdminGameSocket"
;
import
{
useAdminGameSocket
}
from
"@/composables/useAdminGameSocket"
;
import
{
onSocketMessage
}
from
"@/commons/ws"
;
import
{
onSocketMessage
}
from
"@/commons/ws"
;
import
type
Player
from
"@/commons/player.ts"
;
import
type
Player
from
"@/commons/player.ts"
;
import
{
useRouter
}
from
'vue-router'
import
{
$remove_socket_storage
}
from
"@/commons/utils.ts"
;
type
GameScreen
=
"loading"
|
"rank1"
|
"rank2"
;
const
router
=
useRouter
()
const
PLAYER_LIMIT
=
20
;
type
GameScreen
=
'loading'
|
'rank1'
|
'rank2'
const
RANK_LIMIT
=
10
;
const
PLAYER_LIMIT
=
20
const
RANK_LIMIT
=
10
const
emptyLoadingPlayer
=
()
=>
({
const
emptyLoadingPlayer
=
()
=>
({
score
:
0
,
score
:
'-'
,
telephone
:
""
,
telephone
:
''
,
userid
:
""
,
userid
:
''
,
wechat_id
:
""
,
wechat_id
:
''
,
nickname
:
"虚位以待"
,
nickname
:
'虚位以待'
,
avatar
:
""
,
avatar
:
''
,
})
;
})
const
emptyRankPlayer
=
(
index
:
number
):
Player
=>
({
const
emptyRankPlayer
=
(
index
:
number
):
Player
=>
({
active
:
false
,
wechat_id
:
`empty-
${
index
}
`
,
wechat_id
:
`empty-
${
index
}
`
,
nickname
:
"虚位以待"
,
nickname
:
'虚位以待'
,
avatar
:
""
,
avatar
:
''
,
score
:
0
,
score
:
'-'
,
});
})
const
screen
=
ref
<
GameScreen
>
(
"loading"
);
const
screen
=
ref
<
GameScreen
>
(
'loading'
)
const
loadingPlayers
=
ref
<
any
[]
>
(
const
loadingPlayers
=
ref
<
any
[]
>
(
Array
.
from
({
length
:
PLAYER_LIMIT
},
emptyLoadingPlayer
))
Array
.
from
({
length
:
PLAYER_LIMIT
},
emptyLoadingPlayer
),
const
playerCount
=
ref
(
0
)
);
const
rankPlayers
=
ref
<
Player
[]
>
(
Array
.
from
({
length
:
RANK_LIMIT
},
(
_
,
index
)
=>
emptyRankPlayer
(
index
)))
const
playerCount
=
ref
(
0
);
const
rank1Ref
=
ref
<
InstanceType
<
typeof
Rank1
>
|
null
>
(
null
)
const
rankPlayers
=
ref
<
Player
[]
>
(
let
isPlayingStartAnimation
=
false
Array
.
from
({
length
:
RANK_LIMIT
},
(
_
,
index
)
=>
emptyRankPlayer
(
index
)),
);
const
confirmRefresh
=
(
event
:
BeforeUnloadEvent
)
=>
{
const
rank1Ref
=
ref
<
InstanceType
<
typeof
Rank1
>
|
null
>
(
null
);
// closeRoom();
let
isPlayingStartAnimation
=
false
;
event
.
preventDefault
()
event
.
returnValue
=
''
// H5 操控传来的加速度: { [userid]: boost(叠加系数, 0~N) }
}
const
horseBoosts
=
ref
<
Record
<
string
,
number
>>
({});
const
renderPlayers
=
(
data
:
any
)
=>
{
const
players
=
Array
.
isArray
(
data
?.
list
)
?
data
.
list
:
[]
playerCount
.
value
=
Number
(
data
?.
count
??
players
.
length
)
loadingPlayers
.
value
=
Array
.
from
(
{
length
:
PLAYER_LIMIT
},
(
_
,
index
)
=>
players
[
index
]
??
emptyLoadingPlayer
(),
)
}
const
updateRankPlayers
=
(
data
:
any
)
=>
{
if
(
!
Array
.
isArray
(
data
))
return
rankPlayers
.
value
=
Array
.
from
(
{
length
:
RANK_LIMIT
},
(
_
,
index
)
=>
data
[
index
]
??
emptyRankPlayer
(
index
),
)
}
const
playerToRankPlayer
=
(
player
:
any
,
index
:
number
):
Player
=>
({
telephone
:
player
?.
telephone
??
''
,
userid
:
player
?.
userid
??
''
,
wechat_id
:
player
?.
wechat_id
||
`empty-
${
index
}
`
,
nickname
:
player
?.
nickname
||
'虚位以待'
,
avatar
:
player
?.
avatar
||
''
,
score
:
player
?.
score
??
'-'
,
})
const
seedRankPlayersFromLoading
=
()
=>
{
rankPlayers
.
value
=
Array
.
from
(
{
length
:
RANK_LIMIT
},
(
_
,
index
)
=>
{
const
player
=
loadingPlayers
.
value
[
index
]
if
(
!
player
?.
userid
&&
!
player
?.
wechat_id
)
{
return
emptyRankPlayer
(
index
)
}
return
playerToRankPlayer
(
player
,
index
)
},
)
}
let
offHorseBoost
:
(()
=>
void
)
|
undefined
;
const
resetRoundState
=
()
=>
{
playerCount
.
value
=
0
loadingPlayers
.
value
=
Array
.
from
({
length
:
PLAYER_LIMIT
},
emptyLoadingPlayer
)
rankPlayers
.
value
=
Array
.
from
({
length
:
RANK_LIMIT
},
(
_
,
index
)
=>
emptyRankPlayer
(
index
))
isPlayingStartAnimation
=
false
}
const
gotoLoading
=
(
reset
=
false
)
=>
{
if
(
reset
)
{
resetRoundState
()
}
screen
.
value
=
'loading'
}
// 监听 WebSocket 获取 H5 玩家操控的马匹加速度
const
gotoRank1WithIntro
=
async
()
=>
{
offHorseBoost
=
onSocketMessage
((
evt
,
payload
)
=>
{
if
(
isPlayingStartAnimation
)
return
isPlayingStartAnimation
=
true
seedRankPlayersFromLoading
()
screen
.
value
=
'rank1'
await
nextTick
()
await
rank1Ref
.
value
?.
startIntro
()
screen
.
value
=
'rank2'
isPlayingStartAnimation
=
false
}
const
horseBoosts
=
ref
<
Record
<
string
,
number
>>
({});
const
gameId
=
'game4'
const
{
startGame
,
createRoom
,
backRoom
,
closeRoom
}
=
useAdminGameSocket
({
gameId
,
onAny
:
(
evt
,
payload
)
=>
{
const
data
=
payload
?.
data
??
payload
;
const
data
=
payload
?.
data
??
payload
;
// 调试日志:打印 WebSocket 原始数据
// 调试日志:打印 WebSocket 原始数据
...
@@ -81,125 +155,281 @@ offHorseBoost = onSocketMessage((evt, payload) => {
...
@@ -81,125 +155,281 @@ offHorseBoost = onSocketMessage((evt, payload) => {
console
.
log
(
"[Game4 WebSocket] 解析到加速数据:"
,
boosts
);
console
.
log
(
"[Game4 WebSocket] 解析到加速数据:"
,
boosts
);
horseBoosts
.
value
=
{
...
boosts
};
horseBoosts
.
value
=
{
...
boosts
};
}
}
});
},
onRoomState
:
(
data
:
any
)
=>
{
const
confirmRefresh
=
(
event
:
BeforeUnloadEvent
)
=>
{
event
.
preventDefault
();
event
.
returnValue
=
""
;
};
const
renderPlayers
=
(
data
:
any
)
=>
{
const
players
=
Array
.
isArray
(
data
?.
list
)
?
data
.
list
:
[];
playerCount
.
value
=
Number
(
data
?.
count
??
players
.
length
);
loadingPlayers
.
value
=
Array
.
from
(
{
length
:
PLAYER_LIMIT
},
(
_
,
index
)
=>
players
[
index
]
??
emptyLoadingPlayer
(),
);
};
const
updateRankPlayers
=
(
data
:
any
)
=>
{
if
(
!
Array
.
isArray
(
data
))
return
;
rankPlayers
.
value
=
Array
.
from
(
{
length
:
RANK_LIMIT
},
(
_
,
index
)
=>
data
[
index
]
??
emptyRankPlayer
(
index
),
);
};
const
gotoLoading
=
(
reset
=
false
)
=>
{
if
(
reset
)
{
playerCount
.
value
=
0
;
loadingPlayers
.
value
=
Array
.
from
(
{
length
:
PLAYER_LIMIT
},
emptyLoadingPlayer
,
);
rankPlayers
.
value
=
Array
.
from
(
{
length
:
RANK_LIMIT
},
(
_
,
index
)
=>
emptyRankPlayer
(
index
),
);
isPlayingStartAnimation
=
false
;
}
screen
.
value
=
"loading"
;
};
const
gotoRank1WithIntro
=
async
()
=>
{
if
(
isPlayingStartAnimation
)
return
;
isPlayingStartAnimation
=
true
;
screen
.
value
=
"rank1"
;
await
nextTick
();
await
rank1Ref
.
value
?.
startIntro
();
// 结果页已在 Rank1View 内部渲染,不需要切到 rank2
isPlayingStartAnimation
=
false
;
};
function
handleRoomState
(
data
:
any
)
{
if
(
Array
.
isArray
(
data
?.
list
))
{
if
(
Array
.
isArray
(
data
?.
list
))
{
renderPlayers
(
data
);
renderPlayers
(
data
)
}
}
switch
(
data
?.
status
)
{
switch
(
data
?.
status
)
{
case
0
:
case
0
:
gotoLoading
(
true
);
gotoLoading
(
true
)
createRoom
(
4
);
createRoom
(
4
)
break
;
break
case
1
:
case
1
:
gotoLoading
();
// if(data.gameId && data.gameId!=gameId){
break
;
// return;
// }
gotoLoading
()
break
case
2
:
case
2
:
screen
.
value
=
"rank1"
;
seedRankPlayersFromLoading
()
break
;
screen
.
value
=
'rank1'
break
case
3
:
case
3
:
screen
.
value
=
"rank2"
;
screen
.
value
=
'rank2'
break
;
break
}
}
}
},
const
{
startGame
,
createRoom
,
backRoom
,
requestRoomState
}
=
useAdminGameSocket
({
gameId
:
"game4"
,
// loginRedirectPath: '/game4',
onRoomState
:
handleRoomState
,
onRoomJoin
:
(
data
)
=>
{
onRoomJoin
:
(
data
)
=>
{
renderPlayers
(
data
);
renderPlayers
(
data
)
gotoLoading
();
gotoLoading
()
},
},
onGameStart
:
gotoRank1WithIntro
,
onGameStart
:
gotoRank1WithIntro
,
onRoomRank
:
updateRankPlayers
,
onRoomRank
:
updateRankPlayers
,
});
onRelogin
:
async
()
=>
{
$remove_socket_storage
();
await
router
.
replace
(
'/'
)
}
})
const
startGameWithMusic
=
()
=>
{
if
(
playerCount
.
value
==
0
)
{
alert
(
'房间中没有玩家'
)
return
;
}
startGame
()
}
const
nextRound
=
()
=>
{
const
nextRound
=
()
=>
{
gotoLoading
(
true
);
gotoLoading
(
true
)
// 使用 backRoom 重置已有房间,而非 createRoom 重复创建
//重开房间
backRoom
(
1
);
backRoom
(
4
)
setTimeout
(()
=>
{
}
requestRoomState
();
},
200
);
const
nextRoundWithMusic
=
()
=>
{
};
nextRound
()
}
const
backHandler
=
()
=>
{
if
(
confirm
(
'是否关闭当前房间回到首页'
))
{
closeRoom
();
stopGame4Music
()
router
.
replace
(
'/main'
);
}
}
onMounted
(()
=>
{
onMounted
(()
=>
{
window
.
addEventListener
(
"beforeunload"
,
confirmRefresh
);
window
.
addEventListener
(
'beforeunload'
,
confirmRefresh
)
});
playGame4Music
()
})
onUnmounted
(()
=>
{
onUnmounted
(()
=>
{
window
.
removeEventListener
(
"beforeunload"
,
confirmRefresh
);
stopAllMusic
()
offHorseBoost
?.();
window
.
removeEventListener
(
'beforeunload'
,
confirmRefresh
)
});
})
watch
(
screen
,
(
value
)
=>
{
// console.log(value);
if
(
value
==
'rank2'
)
{
playApplauseMusic
();
}
else
if
(
value
==
'loading'
)
{
playGame4Music
();
}
})
// type GameScreen = "loading" | "rank1" | "rank2";
// const PLAYER_LIMIT = 20;
// const RANK_LIMIT = 10;
// const emptyLoadingPlayer = () => ({
// score: 0,
// telephone: "",
// userid: "",
// wechat_id: "",
// nickname: "虚位以待",
// avatar: "",
// });
// const emptyRankPlayer = (index: number): Player => ({
// active: false,
// wechat_id: `empty-${index}`,
// nickname: "虚位以待",
// avatar: "",
// score: 0,
// });
// const screen = ref
<
GameScreen
>
(
"loading"
);
// const loadingPlayers = ref
<
any
[]
>
(
// Array.from({ length: PLAYER_LIMIT }, emptyLoadingPlayer),
// );
// const playerCount = ref(0);
// const rankPlayers = ref
<
Player
[]
>
(
// Array.from({ length: RANK_LIMIT }, (_, index) => emptyRankPlayer(index)),
// );
// const rank1Ref = ref
<
InstanceType
<
typeof
Rank1
>
|
null
>
(
null
);
// let isPlayingStartAnimation = false;
// // H5 操控传来的加速度: { [userid]: boost(叠加系数, 0~N) }
// const horseBoosts = ref
<
Record
<
string
,
number
>>
({});
// let offHorseBoost: (() => void) | undefined;
// // 监听 WebSocket 获取 H5 玩家操控的马匹加速度
// offHorseBoost = onSocketMessage((evt, payload) => {
// const data = payload?.data ?? payload;
// // 调试日志:打印 WebSocket 原始数据
// console.log("[Game4 WebSocket] 收到消息:", {
// event: evt,
// payloadType: typeof payload,
// dataType: typeof data,
// isArray: Array.isArray(data),
// rawPayload: payload,
// });
// if (!Array.isArray(data)) return;
// const boosts: Record
<
string
,
number
>
=
{};
// let hasBoost = false;
// data.forEach((item: any) => {
// // WebSocket 数据无 userid/wechat_id,用 avatar 作为稳定标识
// const id = item.userid || item.wechat_id || item.avatar || "";
// if (!id) return;
// // 尝试多种字段名: score / boost / acceleration / speed / progress
// const raw = item.score ?? item.boost ?? item.acceleration ?? item.speed ?? item.progress;
// if (raw === undefined || raw === null) return;
// const val = Number(raw);
// if (isNaN(val)) return;
// // score/boost 范围 0~N,0 表示无加速,越大越快
// boosts[id] = Math.max(0, val);
// hasBoost = true;
// });
// if (hasBoost) {
// console.log("[Game4 WebSocket] 解析到加速数据:", boosts);
// horseBoosts.value = { ...boosts };
// }
// });
// const confirmRefresh = (event: BeforeUnloadEvent) => {
// event.preventDefault();
// event.returnValue = "";
// };
// const renderPlayers = (data: any) => {
// const players = Array.isArray(data?.list) ? data.list : [];
// playerCount.value = Number(data?.count ?? players.length);
// loadingPlayers.value = Array.from(
// { length: PLAYER_LIMIT },
// (_, index) => players[index] ?? emptyLoadingPlayer(),
// );
// };
// const updateRankPlayers = (data: any) => {
// if (!Array.isArray(data)) return;
// rankPlayers.value = Array.from(
// { length: RANK_LIMIT },
// (_, index) => data[index] ?? emptyRankPlayer(index),
// );
// };
// const gotoLoading = (reset = false) => {
// if (reset) {
// playerCount.value = 0;
// loadingPlayers.value = Array.from(
// { length: PLAYER_LIMIT },
// emptyLoadingPlayer,
// );
// rankPlayers.value = Array.from(
// { length: RANK_LIMIT },
// (_, index) => emptyRankPlayer(index),
// );
// isPlayingStartAnimation = false;
// }
// screen.value = "loading";
// };
// const gotoRank1WithIntro = async () => {
// if (isPlayingStartAnimation) return;
// isPlayingStartAnimation = true;
// screen.value = "rank1";
// await nextTick();
// await rank1Ref.value?.startIntro();
// // 结果页已在 Rank1View 内部渲染,不需要切到 rank2
// isPlayingStartAnimation = false;
// };
// function handleRoomState(data: any) {
// if (Array.isArray(data?.list)) {
// renderPlayers(data);
// }
// switch (data?.status) {
// case 0:
// gotoLoading(true);
// createRoom(4);
// break;
// case 1:
// gotoLoading();
// break;
// case 2:
// screen.value = "rank1";
// break;
// case 3:
// screen.value = "rank2";
// break;
// }
// }
// const { startGame, createRoom, backRoom, requestRoomState, closeRoom } = useAdminGameSocket({
// gameId: "game4",
// // loginRedirectPath: '/game4',
// onRoomState: handleRoomState,
// onRoomJoin: (data) => {
// renderPlayers(data);
// gotoLoading();
// },
// onGameStart: gotoRank1WithIntro,
// onRoomRank: updateRankPlayers,
// });
// const nextRound = () => {
// gotoLoading(true);
// // 使用 backRoom 重置已有房间,而非 createRoom 重复创建
// backRoom(1);
// setTimeout(() => {
// requestRoomState();
// }, 200);
// };
// onMounted(() => {
// window.addEventListener("beforeunload", confirmRefresh);
// playGame4Music()
// });
// onUnmounted(() => {
// stopGame4Music()
// window.removeEventListener("beforeunload", confirmRefresh);
// offHorseBoost?.();
// });
// const backHandler = () => {
// if (confirm('是否关闭当前房间回到首页')) {
// closeRoom();
// stopGame4Music()
// router.replace('/main');
// }
// }
</
script
>
</
script
>
<
template
>
<
template
>
<Loading
<Loading
v-if=
"screen === 'loading'"
:players=
"loadingPlayers"
:player-count=
"playerCount"
v-if=
"screen === 'loading'"
@
start=
"startGameWithMusic"
@
back=
"backHandler"
/>
:players=
"loadingPlayers"
<Rank1
v-if=
"screen === 'rank1'"
ref=
"rank1Ref"
:rank-list=
"rankPlayers"
:horse-boosts=
"horseBoosts"
:player-count=
"playerCount"
@
start=
"startGameWithMusic"
@
next=
"nextRound"
/>
@
start=
"startGame"
/>
<Rank1
v-if=
"screen === 'rank1'"
ref=
"rank1Ref"
:rank-list=
"rankPlayers"
:horse-boosts=
"horseBoosts"
@
start=
"startGame"
@
next=
"nextRound"
/>
<!--
<Rank2
v-else-if=
"screen === 'rank2'"
:rank-list=
"rankPlayers"
@
next=
"nextRound"
/>
-->
<!--
<Rank2
v-else-if=
"screen === 'rank2'"
:rank-list=
"rankPlayers"
@
next=
"nextRound"
/>
-->
</
template
>
</
template
>
frontend-large/src/pages/game4/views/LoadingView.vue
View file @
a8efe97a
...
@@ -11,6 +11,7 @@ defineProps<{
...
@@ -11,6 +11,7 @@ defineProps<{
const
emit
=
defineEmits
<
{
const
emit
=
defineEmits
<
{
start
:
[];
start
:
[];
back
:[];
}
>
();
}
>
();
const
imageUrls
=
{
const
imageUrls
=
{
...
@@ -26,8 +27,10 @@ const imageUrls = {
...
@@ -26,8 +27,10 @@ const imageUrls = {
avatarAnimation
:
cssAssetUrl
(
"avatar_animation.png"
),
avatarAnimation
:
cssAssetUrl
(
"avatar_animation.png"
),
avatar
:
cssAssetUrl
(
"avatar.png"
),
avatar
:
cssAssetUrl
(
"avatar.png"
),
line
:
cssAssetUrl
(
"game1/line.png"
),
line
:
cssAssetUrl
(
"game1/line.png"
),
start1
:
cssAssetUrl
(
"game1/start-1.png"
),
// start1: cssAssetUrl("game1/start-1.png"),
start2
:
cssAssetUrl
(
"game1/start-2.png"
),
// start2: cssAssetUrl("game1/start-2.png"),
start
:
cssAssetUrl
(
'game1/start.png'
),
back
:
cssAssetUrl
(
'game1/back.png'
),
};
};
const
isStartPressed
=
ref
(
false
);
const
isStartPressed
=
ref
(
false
);
...
@@ -67,10 +70,7 @@ const releaseStartButton = () => {
...
@@ -67,10 +70,7 @@ const releaseStartButton = () => {
当前在线人数
<span>
{{
playerCount
}}
</span>
当前在线人数
<span>
{{
playerCount
}}
</span>
</div>
</div>
<div
class=
"list-container-left"
>
<div
class=
"list-container-left"
>
<div
<div
v-for=
"(item, index) in players"
:key=
"item.userid || item.wechat_id || `empty-$
{index}`">
v-for=
"(item, index) in players"
:key=
"item.userid || item.wechat_id || `empty-$
{index}`"
>
<div>
<div>
<div
class=
"img-avatar-container"
>
<div
class=
"img-avatar-container"
>
<div
class=
"img-avatar"
:style=
"`$
{renderAvatar(item)}`">
</div>
<div
class=
"img-avatar"
:style=
"`$
{renderAvatar(item)}`">
</div>
...
@@ -83,14 +83,11 @@ const releaseStartButton = () => {
...
@@ -83,14 +83,11 @@ const releaseStartButton = () => {
</div>
</div>
<div
class=
"list-container-line"
></div>
<div
class=
"list-container-line"
></div>
<div
class=
"list-container-right"
>
<div
class=
"list-container-right"
>
<div
<!--
<div
class=
"btn-start"
:class=
"
{ pressed: isStartPressed }" @pointerdown="pressStartButton"
class=
"btn-start"
@pointerup="releaseStartButton" @pointerleave="releaseStartButton" @pointercancel="releaseStartButton">
:class=
"
{ pressed: isStartPressed }"
</div>
-->
@pointerdown="pressStartButton"
<div
class=
"btn-start"
@
click=
"pressStartButton"
></div>
@pointerup="releaseStartButton"
<div
class=
"btn-back"
@
click=
"emit('back')"
></div>
@pointerleave="releaseStartButton"
@pointercancel="releaseStartButton"
>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
...
@@ -148,6 +145,7 @@ const releaseStartButton = () => {
...
@@ -148,6 +145,7 @@ const releaseStartButton = () => {
width
:
100%
;
width
:
100%
;
height
:
144px
;
height
:
144px
;
border-radius
:
10px
;
border-radius
:
10px
;
img
{
img
{
width
:
140px
;
width
:
140px
;
height
:
140px
;
height
:
140px
;
...
@@ -159,6 +157,7 @@ const releaseStartButton = () => {
...
@@ -159,6 +157,7 @@ const releaseStartButton = () => {
color
:
white
;
color
:
white
;
}
}
}
}
.img-gift
{
.img-gift
{
background
:
v-bind
(
"imageUrls.gift"
)
no-repeat
;
background
:
v-bind
(
"imageUrls.gift"
)
no-repeat
;
width
:
315px
;
width
:
315px
;
...
@@ -167,6 +166,7 @@ const releaseStartButton = () => {
...
@@ -167,6 +166,7 @@ const releaseStartButton = () => {
top
:
124px
;
top
:
124px
;
right
:
320px
;
right
:
320px
;
}
}
.img-small-gu
{
.img-small-gu
{
background
:
v-bind
(
"imageUrls.smallGu"
)
no-repeat
;
background
:
v-bind
(
"imageUrls.smallGu"
)
no-repeat
;
width
:
161px
;
width
:
161px
;
...
@@ -175,6 +175,7 @@ const releaseStartButton = () => {
...
@@ -175,6 +175,7 @@ const releaseStartButton = () => {
top
:
500px
;
top
:
500px
;
right
:
340px
;
right
:
340px
;
}
}
.img-gu
{
.img-gu
{
background
:
v-bind
(
"imageUrls.gu"
)
no-repeat
;
background
:
v-bind
(
"imageUrls.gu"
)
no-repeat
;
width
:
320px
;
width
:
320px
;
...
@@ -199,7 +200,7 @@ const releaseStartButton = () => {
...
@@ -199,7 +200,7 @@ const releaseStartButton = () => {
color
:
#aa0000
;
color
:
#aa0000
;
font-weight
:
bold
;
font-weight
:
bold
;
>
span
{
>span
{
margin-left
:
20px
;
margin-left
:
20px
;
font-size
:
48px
;
font-size
:
48px
;
position
:
relative
;
position
:
relative
;
...
@@ -266,13 +267,21 @@ const releaseStartButton = () => {
...
@@ -266,13 +267,21 @@ const releaseStartButton = () => {
width
:
316px
;
width
:
316px
;
height
:
105px
;
height
:
105px
;
margin-left
:
60px
;
margin-left
:
60px
;
margin-top
:
8
0px
;
margin-top
:
1
0px
;
background
:
v-bind
(
"imageUrls.start
1
"
);
background
:
v-bind
(
"imageUrls.start"
);
cursor
:
pointer
;
cursor
:
pointer
;
}
}
.btn-start.pressed
{
/*
.btn-start.pressed {
background: v-bind("imageUrls.start2");
background: v-bind("imageUrls.start2");
} */
.btn-back
{
width
:
316px
;
height
:
105px
;
margin-left
:
60px
;
margin-top
:
30px
;
background
:
v-bind
(
'imageUrls.back'
);
cursor
:
pointer
;
}
}
}
}
}
}
...
...
frontend-large/src/pages/game5/Game5.vue
View file @
a8efe97a
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
nextTick
,
onMounted
,
onUnmounted
,
ref
}
from
'vue'
import
{
nextTick
,
onMounted
,
onUnmounted
,
ref
,
watch
}
from
'vue'
import
{
useRouter
}
from
'vue-router'
import
{
useRouter
}
from
'vue-router'
import
Loading
from
'./views/LoadingView.vue'
import
Loading
from
'./views/LoadingView.vue'
import
Rank1
from
'./views/Rank1View.vue'
import
Rank1
from
'./views/Rank1View.vue'
import
Rank2
from
'./views/Rank2View.vue'
import
Rank2
from
'./views/Rank2View.vue'
import
{
useAdminGameSocket
}
from
'@/composables/useAdminGameSocket'
import
{
useAdminGameSocket
}
from
'@/composables/useAdminGameSocket'
import
type
Player
from
'@/commons/player.ts'
import
type
Player
from
'@/commons/player.ts'
import
{
play
Game1
Music
}
from
'@/commons/music'
import
{
play
ApplauseMusic
,
playGame5Music
,
stopAllMusic
,
stopGame5
Music
}
from
'@/commons/music'
import
{
$remove_socket_storage
}
from
'@/commons/utils.ts'
import
{
$remove_socket_storage
}
from
'@/commons/utils.ts'
const
router
=
useRouter
()
const
router
=
useRouter
()
...
@@ -124,7 +124,7 @@ function handleRoomState(data: any) {
...
@@ -124,7 +124,7 @@ function handleRoomState(data: any) {
switch
(
data
?.
status
)
{
switch
(
data
?.
status
)
{
case
0
:
case
0
:
gotoLoading
(
true
)
gotoLoading
(
true
)
createRoom
(
1
)
createRoom
(
5
)
break
break
case
1
:
case
1
:
gotoLoading
()
gotoLoading
()
...
@@ -139,7 +139,7 @@ function handleRoomState(data: any) {
...
@@ -139,7 +139,7 @@ function handleRoomState(data: any) {
}
}
}
}
const
{
startGame
,
createRoom
,
backRoom
}
=
useAdminGameSocket
({
const
{
startGame
,
createRoom
,
closeRoom
,
backRoom
}
=
useAdminGameSocket
({
gameId
:
'game5'
,
gameId
:
'game5'
,
onRoomState
:
handleRoomState
,
onRoomState
:
handleRoomState
,
onRoomJoin
:
(
data
)
=>
{
onRoomJoin
:
(
data
)
=>
{
...
@@ -166,34 +166,52 @@ const startGameWithMusic = () => {
...
@@ -166,34 +166,52 @@ const startGameWithMusic = () => {
alert
(
'房间中没有玩家'
)
alert
(
'房间中没有玩家'
)
return
;
return
;
}
}
playGame
1
Music
()
playGame
5
Music
()
startGame
()
startGame
()
}
}
const
nextRound
=
()
=>
{
const
nextRound
=
()
=>
{
gotoLoading
(
true
)
gotoLoading
(
true
)
//重开房间
//重开房间
backRoom
(
1
)
backRoom
(
5
)
}
}
const
nextRoundWithMusic
=
()
=>
{
const
nextRoundWithMusic
=
()
=>
{
playGame
1
Music
()
playGame
5
Music
()
nextRound
()
nextRound
()
}
}
onMounted
(()
=>
{
onMounted
(()
=>
{
window
.
addEventListener
(
'beforeunload'
,
confirmRefresh
)
window
.
addEventListener
(
'beforeunload'
,
confirmRefresh
)
playGame
1
Music
()
playGame
5
Music
()
})
})
onUnmounted
(()
=>
{
onUnmounted
(()
=>
{
stopAllMusic
()
window
.
removeEventListener
(
'beforeunload'
,
confirmRefresh
)
window
.
removeEventListener
(
'beforeunload'
,
confirmRefresh
)
})
})
const
backHandler
=
()
=>
{
if
(
confirm
(
'是否关闭当前房间回到首页'
))
{
closeRoom
();
stopGame5Music
()
router
.
replace
(
'/main'
);
}
}
watch
(
screen
,
(
value
)
=>
{
// console.log(value);
if
(
value
==
'rank2'
){
playApplauseMusic
();
}
else
if
(
value
==
'loading'
){
playGame5Music
();
}
})
</
script
>
</
script
>
<
template
>
<
template
>
<Loading
v-if=
"screen === 'loading'"
:players=
"loadingPlayers"
:player-count=
"playerCount"
<Loading
v-if=
"screen === 'loading'"
:players=
"loadingPlayers"
:player-count=
"playerCount"
@
start=
"startGameWithMusic"
/>
@
start=
"startGameWithMusic"
@
back=
"backHandler"
/>
<Rank1
v-else-if=
"screen === 'rank1'"
ref=
"rank1Ref"
:rank-list=
"rankPlayers"
@
start=
"startGameWithMusic"
<Rank1
v-else-if=
"screen === 'rank1'"
ref=
"rank1Ref"
:rank-list=
"rankPlayers"
@
start=
"startGameWithMusic"
@
next=
"nextRoundWithMusic"
/>
@
next=
"nextRoundWithMusic"
/>
<!--
<Rank1
v-else
ref=
"rank1Ref"
:rank-list=
"rankPlayers"
@
start=
"startGameWithMusic"
--
>
<!--
<Rank1
v-else
ref=
"rank1Ref"
:rank-list=
"rankPlayers"
@
start=
"startGameWithMusic"
--
>
...
...
frontend-large/src/pages/game5/views/LoadingView.vue
View file @
a8efe97a
...
@@ -11,6 +11,7 @@ defineProps<{
...
@@ -11,6 +11,7 @@ defineProps<{
const
emit
=
defineEmits
<
{
const
emit
=
defineEmits
<
{
start
:
[];
start
:
[];
back
:
[];
}
>
();
}
>
();
const
imageUrls
=
{
const
imageUrls
=
{
...
@@ -25,8 +26,10 @@ const imageUrls = {
...
@@ -25,8 +26,10 @@ const imageUrls = {
avatarAnimation
:
cssAssetUrl
(
'avatar_animation.png'
),
avatarAnimation
:
cssAssetUrl
(
'avatar_animation.png'
),
avatar
:
cssAssetUrl
(
'avatar.png'
),
avatar
:
cssAssetUrl
(
'avatar.png'
),
line
:
cssAssetUrl
(
'game1/line.png'
),
line
:
cssAssetUrl
(
'game1/line.png'
),
start1
:
cssAssetUrl
(
'game1/start-1.png'
),
// start1: cssAssetUrl('game1/start-1.png'),
start2
:
cssAssetUrl
(
'game1/start-2.png'
),
// start2: cssAssetUrl('game1/start-2.png'),
start
:
cssAssetUrl
(
'game1/start.png'
),
back
:
cssAssetUrl
(
'game1/back.png'
),
};
};
const
isStartPressed
=
ref
(
false
);
const
isStartPressed
=
ref
(
false
);
...
@@ -74,14 +77,16 @@ const renderAvatar = (item: any | null) => {
...
@@ -74,14 +77,16 @@ const renderAvatar = (item: any | null) => {
</div>
</div>
<div
class=
"list-container-line"
></div>
<div
class=
"list-container-line"
></div>
<div
class=
"list-container-right"
>
<div
class=
"list-container-right"
>
<div
<
!--
<
div
class=
"btn-start"
class=
"btn-start"
:class=
"
{ pressed: isStartPressed }"
:class=
"
{ pressed: isStartPressed }"
@pointerdown="pressStartButton"
@pointerdown="pressStartButton"
@pointerup="releaseStartButton"
@pointerup="releaseStartButton"
@pointerleave="releaseStartButton"
@pointerleave="releaseStartButton"
@pointercancel="releaseStartButton"
@pointercancel="releaseStartButton"
>
</div>
>
</div>
-->
<div
class=
"btn-start"
@
click=
"pressStartButton"
></div>
<div
class=
"btn-back"
@
click=
"emit('back')"
></div>
</div>
</div>
</div>
</div>
</div>
</div>
...
@@ -139,6 +144,7 @@ const renderAvatar = (item: any | null) => {
...
@@ -139,6 +144,7 @@ const renderAvatar = (item: any | null) => {
width
:
100%
;
width
:
100%
;
height
:
144px
;
height
:
144px
;
border-radius
:
10px
;
border-radius
:
10px
;
img
{
img
{
width
:
147px
;
width
:
147px
;
height
:
147px
;
height
:
147px
;
...
@@ -159,6 +165,7 @@ const renderAvatar = (item: any | null) => {
...
@@ -159,6 +165,7 @@ const renderAvatar = (item: any | null) => {
top
:
193px
;
top
:
193px
;
left
:
47px
;
left
:
47px
;
}
}
.img-right
{
.img-right
{
background
:
v-bind
(
'imageUrls.right'
)
no-repeat
;
background
:
v-bind
(
'imageUrls.right'
)
no-repeat
;
width
:
423px
;
width
:
423px
;
...
@@ -251,13 +258,21 @@ const renderAvatar = (item: any | null) => {
...
@@ -251,13 +258,21 @@ const renderAvatar = (item: any | null) => {
width
:
316px
;
width
:
316px
;
height
:
105px
;
height
:
105px
;
margin-left
:
60px
;
margin-left
:
60px
;
margin-top
:
8
0px
;
margin-top
:
1
0px
;
background
:
v-bind
(
'imageUrls.start
1
'
);
background
:
v-bind
(
'imageUrls.start'
);
cursor
:
pointer
;
cursor
:
pointer
;
}
}
.btn-start.pressed
{
/*
.btn-start.pressed {
background: v-bind('imageUrls.start2');
background: v-bind('imageUrls.start2');
} */
.btn-back
{
width
:
316px
;
height
:
105px
;
margin-left
:
60px
;
margin-top
:
30px
;
background
:
v-bind
(
'imageUrls.back'
);
cursor
:
pointer
;
}
}
}
}
}
}
...
...
frontend-large/src/pages/game6/Game.vue
View file @
a8efe97a
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
nextTick
,
onMounted
,
onUnmounted
,
ref
}
from
'vue'
import
{
nextTick
,
onMounted
,
onUnmounted
,
ref
,
watch
}
from
'vue'
import
{
useRouter
}
from
'vue-router'
import
{
useRouter
}
from
'vue-router'
import
Loading
from
'./views/LoadingView.vue'
import
Loading
from
'./views/LoadingView.vue'
import
Rank1
from
'./views/Rank1View.vue'
import
Rank1
from
'./views/Rank1View.vue'
import
Rank2
from
'./views/Rank2View.vue'
import
Rank2
from
'./views/Rank2View.vue'
import
{
useAdminGameSocket
}
from
'@/composables/useAdminGameSocket'
import
{
useAdminGameSocket
}
from
'@/composables/useAdminGameSocket'
import
type
Player
from
'@/commons/player.ts'
import
type
Player
from
'@/commons/player.ts'
import
{
play
Game6
Music
,
stopGame6Music
}
from
'@/commons/music'
import
{
play
ApplauseMusic
,
playGame6Music
,
stopAll
Music
,
stopGame6Music
}
from
'@/commons/music'
import
{
$remove_socket_storage
}
from
'@/commons/utils.ts'
import
{
$remove_socket_storage
}
from
'@/commons/utils.ts'
const
router
=
useRouter
()
const
router
=
useRouter
()
...
@@ -135,9 +135,9 @@ function handleRoomState(data: any) {
...
@@ -135,9 +135,9 @@ function handleRoomState(data: any) {
break
break
}
}
}
}
const
gameId
=
'game6'
const
{
startGame
,
createRoom
,
backRoom
,
closeRoom
}
=
useAdminGameSocket
({
const
{
startGame
,
createRoom
,
backRoom
,
closeRoom
}
=
useAdminGameSocket
({
gameId
:
'game6'
,
gameId
,
onRoomState
:
handleRoomState
,
onRoomState
:
handleRoomState
,
onRoomJoin
:
(
data
)
=>
{
onRoomJoin
:
(
data
)
=>
{
renderPlayers
(
data
)
renderPlayers
(
data
)
...
@@ -183,9 +183,18 @@ onMounted(() => {
...
@@ -183,9 +183,18 @@ onMounted(() => {
})
})
onUnmounted
(()
=>
{
onUnmounted
(()
=>
{
stop
Game6
Music
();
stop
All
Music
();
window
.
removeEventListener
(
'beforeunload'
,
confirmRefresh
)
window
.
removeEventListener
(
'beforeunload'
,
confirmRefresh
)
})
})
watch
(
screen
,
(
value
)
=>
{
// console.log(value);
if
(
value
==
'rank2'
){
playApplauseMusic
();
}
else
if
(
value
==
'loading'
){
playGame6Music
();
}
})
</
script
>
</
script
>
<
template
>
<
template
>
...
...
frontend-large/src/pages/game6/views/Rank2View.vue
View file @
a8efe97a
...
@@ -89,7 +89,7 @@ const renderAvatar = (item: any | null) => {
...
@@ -89,7 +89,7 @@ const renderAvatar = (item: any | null) => {
<div
class=
"no-icon"
>
{{
index
+
4
}}
</div>
<div
class=
"no-icon"
>
{{
index
+
4
}}
</div>
<div>
<div>
<div
class=
"img-avatar-container"
>
<div
class=
"img-avatar-container"
>
<div
class=
"img-avatar"
></div>
<div
class=
"img-avatar"
:style=
"`$
{renderAvatar(list[index + 3])}`"
>
</div>
</div>
</div>
<div
class=
"txt-nickname"
>
{{
item
.
nickname
}}
</div>
<div
class=
"txt-nickname"
>
{{
item
.
nickname
}}
</div>
</div>
</div>
...
...
frontend-large/src/router/index.ts
View file @
a8efe97a
import
{
createRouter
,
createWebHashHistory
}
from
'vue-router'
import
{
createRouter
,
createWebHashHistory
}
from
'vue-router'
import
{
$read
}
from
'@/commons/utils'
import
{
$read
}
from
'@/commons/utils'
import
Login
from
'@/pages/Login.vue'
import
Main
from
'@/pages/Main.vue'
import
Main
from
'@/pages/Main.vue'
import
Game1
from
'@/pages/game1/Game.vue'
import
Game1
from
'@/pages/game1/Game.vue'
import
Game4
from
'@/pages/game4/Game4.vue'
import
Game4
from
'@/pages/game4/Game4.vue'
...
@@ -11,12 +13,20 @@ const router = createRouter({
...
@@ -11,12 +13,20 @@ const router = createRouter({
routes
:
[
routes
:
[
{
{
path
:
'/'
,
path
:
'/'
,
redirect
:
()
=>
(
$read
(
'token'
,
''
)
?
'/game1'
:
'/main'
),
redirect
:
()
=>
(
$read
(
'token'
,
''
)
?
'/main'
:
'/login'
),
},
{
path
:
'/login'
,
name
:
'Login'
,
component
:
Login
,
},
},
{
{
path
:
'/main'
,
path
:
'/main'
,
name
:
'Main'
,
name
:
'Main'
,
component
:
Main
,
component
:
Main
,
meta
:
{
requiresAuth
:
true
,
},
},
},
{
{
path
:
'/game1'
,
path
:
'/game1'
,
...
...
frontend-large/vite.config.ts
View file @
a8efe97a
...
@@ -26,7 +26,7 @@ function copyImageAssets() {
...
@@ -26,7 +26,7 @@ function copyImageAssets() {
}
}
export
default
defineConfig
(({
command
})
=>
({
export
default
defineConfig
(({
command
})
=>
({
base
:
command
===
'build'
?
'/cc/pc/'
:
'/'
,
base
:
'/'
,
//
command === 'build' ? '/cc/pc/' : '/',
define
:
{
define
:
{
__APP_DOMAIN__
:
JSON
.
stringify
(
command
===
'build'
?
buildDomain
:
''
),
__APP_DOMAIN__
:
JSON
.
stringify
(
command
===
'build'
?
buildDomain
:
''
),
// __APP_DOMAIN__: JSON.stringify(buildDomain),
// __APP_DOMAIN__: JSON.stringify(buildDomain),
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment