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
026f16bd
Commit
026f16bd
authored
Jun 12, 2026
by
董政锦
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix
parent
6d5045b7
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
42 additions
and
23 deletions
+42
-23
music.ts
frontend-large/src/commons/music.ts
+31
-6
Game4.vue
frontend-large/src/pages/game4/Game4.vue
+6
-11
Rank1View.vue
frontend-large/src/pages/game4/views/Rank1View.vue
+5
-6
No files found.
frontend-large/src/commons/music.ts
View file @
026f16bd
...
...
@@ -26,18 +26,25 @@ export function stopAllMusic() {
backgroundMusic
=
null
;
}
function
getBackgroundMusic
(
music
:
string
,
force
:
boolean
=
true
)
{
if
(
force
)
{
//
function
getBackgroundMusic
(
music
:
string
,
force
:
boolean
=
false
)
{
console
.
log
(
'[Music] getBackgroundMusic called, music:'
,
music
,
'force:'
,
force
,
'current backgroundMusic:'
,
backgroundMusic
?.
src
)
// 检查当前背景音乐是否是同一首(比较路径末尾,处理相对路径和完整URL的情况)
const
isSameMusic
=
backgroundMusic
&&
(
backgroundMusic
.
src
===
music
||
backgroundMusic
.
src
.
endsWith
(
music
));
// 只有在需要切换不同音乐或强制重建时才停止并重建
if
(
force
||
(
!
backgroundMusic
||
!
isSameMusic
))
{
console
.
log
(
'[Music] 重建背景音乐, 原因:'
,
force
?
'强制重建'
:
backgroundMusic
?
'音乐URL变更'
:
'无现有音乐'
)
if
(
backgroundMusic
)
{
stopAllMusic
();
}
}
if
(
!
backgroundMusic
)
{
backgroundMusic
=
new
Audio
(
music
)
backgroundMusic
.
loop
=
true
backgroundMusic
.
preload
=
'auto'
backgroundMusic
.
volume
=
0.6
backgroundMusic
.
load
()
console
.
log
(
'[Music] 新背景音乐创建完成:'
,
backgroundMusic
.
src
)
}
return
backgroundMusic
...
...
@@ -60,7 +67,13 @@ export async function playApplauseMusic() {
export
function
stopApplauseMusic
()
{
window
.
removeEventListener
(
'pointerdown'
,
playApplauseMusic
)
window
.
removeEventListener
(
'keydown'
,
playApplauseMusic
)
backgroundMusic
?.
pause
()
// 只有当当前播放的是喝彩音乐时才暂停,避免误伤背景音乐
if
(
backgroundMusic
&&
backgroundMusic
.
src
.
endsWith
(
applause
))
{
console
.
log
(
'[Music] 停止喝彩音乐'
)
backgroundMusic
.
pause
()
}
else
{
console
.
log
(
'[Music] stopApplauseMusic 被调用,但当前播放的不是喝彩音乐,不暂停'
)
}
}
...
...
@@ -103,13 +116,25 @@ export function stopGame2Music() {
}
export
async
function
playGame4Music
()
{
console
.
log
(
'[Music] playGame4Music called'
)
const
audio
=
getBackgroundMusic
(
game4MusicUrl
)
console
.
log
(
'[Music] 播放音乐文件:'
,
game4MusicUrl
,
'完整路径:'
,
audio
.
src
)
console
.
log
(
'[Music] audio element readyState:'
,
audio
.
readyState
,
'paused:'
,
audio
.
paused
,
'currentTime:'
,
audio
.
currentTime
)
try
{
console
.
log
(
'[Music] 尝试播放音乐...'
)
await
audio
.
play
()
console
.
log
(
'[Music] 音乐播放成功!文件:'
,
game4MusicUrl
,
'paused:'
,
audio
.
paused
,
'currentTime:'
,
audio
.
currentTime
,
'duration:'
,
audio
.
duration
)
// 添加延迟检查,看是否被其他代码暂停
setTimeout
(()
=>
{
console
.
log
(
'[Music] 100ms后检查 - 文件:'
,
game4MusicUrl
,
'paused:'
,
audio
.
paused
,
'currentTime:'
,
audio
.
currentTime
)
},
100
)
window
.
removeEventListener
(
'pointerdown'
,
playGame4Music
)
window
.
removeEventListener
(
'keydown'
,
playGame4Music
)
}
catch
{
}
catch
(
error
)
{
console
.
log
(
'[Music] 音乐播放失败,注册交互监听器:'
,
error
)
window
.
addEventListener
(
'pointerdown'
,
playGame4Music
,
{
once
:
true
})
window
.
addEventListener
(
'keydown'
,
playGame4Music
,
{
once
:
true
})
}
...
...
frontend-large/src/pages/game4/Game4.vue
View file @
026f16bd
...
...
@@ -108,9 +108,7 @@ const gotoRank1WithIntro = async () => {
isPlayingStartAnimation
=
true
seedRankPlayersFromLoading
()
// 对齐 game3:进入赛马画面前确保背景音乐播放中
// 必须在 startIntro 之前调用,因为 startIntro 内部会 stopApplauseMusic() 误伤 BGM
playGame4Music
()
// 参考 game2:不在这里调用 playGame4Music(),依赖 watch 和 pointerdown 监听器触发
screen
.
value
=
'rank1'
await
nextTick
()
await
rank1Ref
.
value
?.
startIntro
()
...
...
@@ -196,22 +194,19 @@ const { startGame, createRoom, backRoom, closeRoom } = useAdminGameSocket({
})
const
startGameWithMusic
=
()
=>
{
// 本地调试模式:跳过 WebSocket,直接进入赛马画面(对齐 game3)
// 注意:不在这里调 playGame4Music(),因为 onMounted 中已注册 pointerdown 监听器,
// 点击按钮时 pointerdown 事件先于 click 触发,会自动播放 BGM。
// 如果在此额外调用 playGame4Music(),会导致 stopAllMusic 销毁并重建 Audio,
// 在复杂时序下可能 play() 失败,需要再点一次页面才能听到音乐。
console
.
log
(
'[Game4] startGameWithMusic called, local mode:'
,
$is_local_mode
(),
'playerCount:'
,
playerCount
.
value
)
// 确保背景音乐播放(参考 game2 的 watch 模式,但直接在点击时调用更可靠)
playGame4Music
()
if
(
$is_local_mode
())
{
console
.
log
(
'[Game4] 本地模式,直接进入赛马画面'
)
gotoRank1WithIntro
()
return
}
if
(
playerCount
.
value
==
0
)
{
// alert('房间中没有玩家')
$toast
(
'房间中没有玩家'
);
return
;
}
// 对齐 game3:点击"开始挑战"时确保背景音乐播放中
playGame4Music
()
console
.
log
(
'[Game4] 调用 startGame()'
)
startGame
()
}
...
...
frontend-large/src/pages/game4/views/Rank1View.vue
View file @
026f16bd
...
...
@@ -335,15 +335,14 @@ const stopMockBoost = () => {
};
const
computeFinalRank
=
():
RankItem
[]
=>
{
// 从 WebSocket rankList 中取有效玩家
// 从 WebSocket rankList 中取有效玩家
(不排序,直接使用 WebSocket 返回的顺序)
const
valid
=
(
props
.
rankList
||
[]).
filter
(
(
p
)
=>
p
.
nickname
!==
"虚位以待"
&&
!
(
p
.
wechat_id
||
""
).
startsWith
(
"empty-"
),
);
if
(
valid
.
length
>
0
)
{
// 优先用 WebSocket 的 score 排序
const
sorted
=
[...
valid
].
sort
((
a
,
b
)
=>
Number
(
b
.
score
??
0
)
-
Number
(
a
.
score
??
0
));
return
sorted
.
map
((
p
,
i
)
=>
({
// 直接使用 WebSocket 返回的顺序,不进行排序
return
valid
.
map
((
p
,
i
)
=>
({
rank
:
i
+
1
,
userid
:
p
.
userid
||
p
.
wechat_id
||
`unknown-
${
i
}
`
,
nickname
:
p
.
nickname
,
...
...
@@ -352,7 +351,7 @@ const computeFinalRank = (): RankItem[] => {
}));
}
// 无 WebSocket 数据时降级:按 xPercent 降序
// 无 WebSocket 数据时降级:按 xPercent 降序
(本地模拟模式)
return
horses
.
value
.
slice
()
.
sort
((
a
,
b
)
=>
b
.
xPercent
-
a
.
xPercent
)
...
...
@@ -404,7 +403,7 @@ const startIntro = async () => {
Object
.
keys
(
prevScores
).
forEach
((
k
)
=>
delete
prevScores
[
k
]);
// 启动完整倒计时:3s 开场 + 3s 游戏(DesignStage 内部管理两个阶段的 UI)
const
countdownPromise
=
designStage
.
value
?.
startCountdown
(
3
,
3
);
const
countdownPromise
=
designStage
.
value
?.
startCountdown
(
3
,
10
);
// 等待 3-2-1 开场倒计时结束(~3.5s 后安全触发)
await
new
Promise
((
r
)
=>
setTimeout
(
r
,
3500
));
...
...
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