Commit bfec4aaa authored by 陈冲's avatar 陈冲
parents e143800b 96495239
...@@ -58,6 +58,7 @@ export function useAdminGameSocket(options: AdminGameSocketOptions) { ...@@ -58,6 +58,7 @@ export function useAdminGameSocket(options: AdminGameSocketOptions) {
validuser: CryptoJS.AES.encrypt(token, passphrase).toString(), validuser: CryptoJS.AES.encrypt(token, passphrase).toString(),
}, },
onConnect: () => { onConnect: () => {
console.log('[useAdminGameSocket] WebSocket 连接成功,gameId:', options.gameId);
if (options.onConnect) { if (options.onConnect) {
if (!options.onConnect()) { if (!options.onConnect()) {
return; return;
...@@ -66,14 +67,16 @@ export function useAdminGameSocket(options: AdminGameSocketOptions) { ...@@ -66,14 +67,16 @@ export function useAdminGameSocket(options: AdminGameSocketOptions) {
window.setTimeout(requestRoomState, 200) window.setTimeout(requestRoomState, 200)
}, },
onDisconnect: (_reason: string) => { onDisconnect: (_reason: string) => {
console.log('[useAdminGameSocket] WebSocket 断开连接,reason:', _reason, 'gameId:', options.gameId);
}, },
onError: (error: any) => { onError: (error: any) => {
// console.error('socket.io connect_error:', error) console.error('[useAdminGameSocket] WebSocket 错误:', error, 'gameId:', options.gameId);
}, },
}) })
offSocketMessage = onSocketMessage(async (evt, payload: SocketPayload) => { offSocketMessage = onSocketMessage(async (evt, payload: SocketPayload) => {
console.log('[useAdminGameSocket] 收到 WebSocket 消息 - evt:', evt, 'payload:', JSON.stringify(payload), 'gameId:', options.gameId);
const { msg, state, data } = payload const { msg, state, data } = payload
if (state === 0) { if (state === 0) {
if (evt == 'login_result') { if (evt == 'login_result') {
......
...@@ -62,12 +62,24 @@ const emptyPlayer = (index: number): Player => ({ ...@@ -62,12 +62,24 @@ const emptyPlayer = (index: number): Player => ({
const list = ref<Player[]>(Array.from({ length: RANK_LIMIT }, (_, index) => emptyPlayer(index))); const list = ref<Player[]>(Array.from({ length: RANK_LIMIT }, (_, index) => emptyPlayer(index)));
const playerKey = (player: Player, index = 0) => { const playerKey = (player: Player, index = 0) => {
// 优先使用 userid/wechat_id
if (player.userid || player.wechat_id) { if (player.userid || player.wechat_id) {
return player.userid || player.wechat_id || `empty-${index}`; const id = player.userid || player.wechat_id;
if (!String(id).startsWith('empty-')) {
return String(id);
} }
if (player.nickname !== '-') {
return `player-${player.nickname}-${player.avatar || ''}`;
} }
// 如果有头像且昵称有效,用 avatar 作为唯一标识
if (player.avatar && player.nickname && player.nickname !== '-' && player.nickname !== '虚位以待') {
return `avt:${player.avatar}`;
}
// 如果昵称有效但没有头像,用昵称作为标识
if (player.nickname && player.nickname !== '-' && player.nickname !== '虚位以待') {
return `name:${player.nickname}`;
}
return `empty-${index}`; return `empty-${index}`;
}; };
......
...@@ -84,14 +84,23 @@ const updateRankPlayers = (data: any) => { ...@@ -84,14 +84,23 @@ const updateRankPlayers = (data: any) => {
console.log('[game2] updateRankPlayers 更新后 rankPlayers:', JSON.stringify(rankPlayers.value.map(p => ({ nickname: p.nickname, userid: p.userid })))) console.log('[game2] updateRankPlayers 更新后 rankPlayers:', JSON.stringify(rankPlayers.value.map(p => ({ nickname: p.nickname, userid: p.userid }))))
} }
const playerToRankPlayer = (player: any, index: number): Player => ({ const playerToRankPlayer = (player: any, index: number): Player => {
// WebSocket 数据可能没有 userid/wechat_id,用 avatar 作为唯一标识
const hasId = player?.userid || player?.wechat_id || player?.openid || player?.user_id;
const avatar = player?.avatar || '';
const nickname = player?.nickname || '虚位以待';
const isRealPlayer = nickname && nickname !== '-' && nickname !== '虚位以待';
const wechat_id = hasId || (isRealPlayer && avatar ? `avt:${avatar}` : `empty-${index}`);
return {
telephone: player?.telephone ?? '', telephone: player?.telephone ?? '',
userid: player?.userid ?? '', userid: hasId || (isRealPlayer && avatar ? `avt:${avatar}` : ''),
wechat_id: player?.wechat_id || `empty-${index}`, wechat_id,
nickname: player?.nickname || '虚位以待', nickname,
avatar: player?.avatar || '', avatar,
score: player?.score ?? '-', score: player?.score ?? '-',
}) };
}
const seedRankPlayersFromLoading = () => { const seedRankPlayersFromLoading = () => {
rankPlayers.value = Array.from( rankPlayers.value = Array.from(
...@@ -138,7 +147,11 @@ const gotoRank1WithIntro = async () => { ...@@ -138,7 +147,11 @@ const gotoRank1WithIntro = async () => {
const gameId = 'game2' const gameId = 'game2'
const { startGame, createRoom, backRoom, closeRoom } = useAdminGameSocket({ const { startGame, createRoom, backRoom, closeRoom } = useAdminGameSocket({
gameId, gameId,
onAny: (evt, payload) => {
console.log("[Game2 WebSocket] 🔥 onAny 触发 - event:", evt, "payload:", JSON.stringify(payload));
},
onRoomState: (data: any) => { onRoomState: (data: any) => {
console.log("[Game2] onRoomState 触发,data:", JSON.stringify(data));
if (Array.isArray(data?.list)) { if (Array.isArray(data?.list)) {
renderPlayers(data) renderPlayers(data)
} }
...@@ -154,7 +167,9 @@ const { startGame, createRoom, backRoom, closeRoom } = useAdminGameSocket({ ...@@ -154,7 +167,9 @@ const { startGame, createRoom, backRoom, closeRoom } = useAdminGameSocket({
gotoLoading() gotoLoading()
break break
case 2: case 2:
console.log("[Game2] status=2,准备进入 rank1,loadingPlayers:", loadingPlayers.value.length);
seedRankPlayersFromLoading() seedRankPlayersFromLoading()
console.log("[Game2] seedRankPlayersFromLoading 后,rankPlayers:", rankPlayers.value.length, JSON.stringify(rankPlayers.value.slice(0, 3)));
screen.value = 'rank1' screen.value = 'rank1'
break break
case 3: case 3:
...@@ -163,11 +178,15 @@ const { startGame, createRoom, backRoom, closeRoom } = useAdminGameSocket({ ...@@ -163,11 +178,15 @@ const { startGame, createRoom, backRoom, closeRoom } = useAdminGameSocket({
} }
}, },
onRoomJoin: (data) => { onRoomJoin: (data) => {
console.log("[Game2] onRoomJoin 触发,data:", JSON.stringify(data));
renderPlayers(data) renderPlayers(data)
gotoLoading() gotoLoading()
}, },
onGameStart: gotoRank1WithIntro, onGameStart: gotoRank1WithIntro,
onRoomRank: updateRankPlayers, onRoomRank: (data) => {
console.log("[Game2] onRoomRank 触发,data:", JSON.stringify(data));
updateRankPlayers(data);
},
onRelogin: async () => { onRelogin: async () => {
$remove_socket_storage(); $remove_socket_storage();
await router.replace('/') await router.replace('/')
......
...@@ -94,9 +94,18 @@ const preloadHorseSprites = () => { ...@@ -94,9 +94,18 @@ const preloadHorseSprites = () => {
}); });
}; };
const playerKey = (player: Player, index = 0) => ( const playerKey = (player: Player, index = 0) => {
String(player.userid || player.wechat_id || player.telephone || `${player.nickname}-${index}`) // 优先使用 userid/wechat_id,没有则用 avatar 作为唯一标识
); const id = player.userid || player.wechat_id || player.telephone;
if (id && !String(id).startsWith('empty-')) return String(id);
// 如果有头像且昵称有效,用 avatar 作为唯一标识
if (player.avatar && player.nickname && player.nickname !== '-' && player.nickname !== '虚位以待') {
return `avt:${player.avatar}`;
}
return `empty-${index}`;
};
const hashKey = (key: string) => Array.from(key).reduce( const hashKey = (key: string) => Array.from(key).reduce(
(hash, character) => ((hash << 5) - hash + character.charCodeAt(0)) | 0, (hash, character) => ((hash << 5) - hash + character.charCodeAt(0)) | 0,
...@@ -113,11 +122,23 @@ const createPaceProfile = (key: string) => { ...@@ -113,11 +122,23 @@ const createPaceProfile = (key: string) => {
}; };
}; };
const isRealPlayer = (player: Player) => ( const isRealPlayer = (player: Player) => {
Boolean(player) if (!player) return false;
&& !String(player.wechat_id || '').startsWith('empty-')
&& player.nickname !== '-' // 检查 wechat_id 是否为空占位
); if (String(player.wechat_id || '').startsWith('empty-')) return false;
// 检查昵称是否有效
if (!player.nickname || player.nickname === '-' || player.nickname === '虚位以待') return false;
// 如果有 userid/wechat_id/telephone,认为是真实玩家
if (player.userid || player.wechat_id || player.telephone) return true;
// 如果有头像,也认为是真实玩家(WebSocket 数据可能没有 ID 字段)
if (player.avatar) return true;
return false;
};
const targetXForRacer = (racer: Racer, rankIndex: number) => { const targetXForRacer = (racer: Racer, rankIndex: number) => {
......
...@@ -128,6 +128,7 @@ const gotoRank1WithIntro = async () => { ...@@ -128,6 +128,7 @@ const gotoRank1WithIntro = async () => {
} }
function handleRoomState(data: any) { function handleRoomState(data: any) {
console.log("[Game3] onRoomState 触发,data:", JSON.stringify(data));
if (Array.isArray(data?.list)) { if (Array.isArray(data?.list)) {
renderPlayers(data) renderPlayers(data)
} }
...@@ -141,6 +142,7 @@ function handleRoomState(data: any) { ...@@ -141,6 +142,7 @@ function handleRoomState(data: any) {
gotoLoading() gotoLoading()
break break
case 2: case 2:
console.log("[Game3] status=2,准备进入 rank1,loadingPlayers:", loadingPlayers.value.length);
// 重连/中途进房时游戏已在运行,直接进入赛马画面 // 重连/中途进房时游戏已在运行,直接进入赛马画面
if (isPlayingStartAnimation) break; if (isPlayingStartAnimation) break;
isPlayingStartAnimation = true; isPlayingStartAnimation = true;
...@@ -161,6 +163,8 @@ const gameId='game3' ...@@ -161,6 +163,8 @@ const gameId='game3'
const { startGame, createRoom, backRoom, closeRoom } = useAdminGameSocket({ const { startGame, createRoom, backRoom, closeRoom } = useAdminGameSocket({
gameId, gameId,
onAny: (evt, payload) => { onAny: (evt, payload) => {
console.log("[Game3 WebSocket] 🔥 onAny 触发 - event:", evt, "payload:", JSON.stringify(payload));
// 兜底处理所有非标准事件,解析玩家实时分数(对齐 game4) // 兜底处理所有非标准事件,解析玩家实时分数(对齐 game4)
const data = payload?.data ?? payload; const data = payload?.data ?? payload;
......
...@@ -92,8 +92,10 @@ const emptyPlayer = (index: number): Player => ({ ...@@ -92,8 +92,10 @@ const emptyPlayer = (index: number): Player => ({
const list = ref<Player[]>(Array.from({ length: RANK_LIMIT }, (_, index) => emptyPlayer(index))); const list = ref<Player[]>(Array.from({ length: RANK_LIMIT }, (_, index) => emptyPlayer(index)));
const updateRankList = (rankList: Player[]) => { const updateRankList = (rankList: Player[]) => {
console.log('[game3 Rank1View] updateRankList 被调用,rankList:', rankList?.length, JSON.stringify(rankList?.slice(0, 3)));
const next = Array.from({ length: RANK_LIMIT }, (_, index) => rankList[index] ?? emptyPlayer(index)); const next = Array.from({ length: RANK_LIMIT }, (_, index) => rankList[index] ?? emptyPlayer(index));
list.value = next; list.value = next;
console.log('[game3 Rank1View] updateRankList 后,list:', list.value.length, '有效玩家数:', list.value.filter(p => getPlayerKey(p).length > 0 && !getPlayerKey(p).startsWith('empty-')).length);
}; };
// ========== 瞬时加速脉冲(对齐 game4 detectScoreChanges) ========== // ========== 瞬时加速脉冲(对齐 game4 detectScoreChanges) ==========
......
...@@ -47,12 +47,14 @@ const confirmRefresh = (event: BeforeUnloadEvent) => { ...@@ -47,12 +47,14 @@ const confirmRefresh = (event: BeforeUnloadEvent) => {
} }
const renderPlayers = (data: any) => { const renderPlayers = (data: any) => {
console.log("[Game4] renderPlayers 被调用,data:", JSON.stringify(data));
const players = Array.isArray(data?.list) ? data.list : [] const players = Array.isArray(data?.list) ? data.list : []
playerCount.value = Number(data?.count ?? players.length) playerCount.value = Number(data?.count ?? players.length)
loadingPlayers.value = Array.from( loadingPlayers.value = Array.from(
{ length: PLAYER_LIMIT }, { length: PLAYER_LIMIT },
(_, index) => players[index] ?? emptyLoadingPlayer(), (_, index) => players[index] ?? emptyLoadingPlayer(),
) )
console.log("[Game4] renderPlayers 完成,loadingPlayers:", loadingPlayers.value.length, "有效玩家:", loadingPlayers.value.filter(p => p.nickname !== '虚位以待').map(p => ({ nickname: p.nickname, userid: p.userid, wechat_id: p.wechat_id, avatar: p.avatar })));
} }
const updateRankPlayers = (data: any) => { const updateRankPlayers = (data: any) => {
...@@ -64,28 +66,43 @@ const updateRankPlayers = (data: any) => { ...@@ -64,28 +66,43 @@ const updateRankPlayers = (data: any) => {
) )
} }
const playerToRankPlayer = (player: any, index: number): Player => ({ const playerToRankPlayer = (player: any, index: number): Player => {
// WebSocket 数据可能没有 userid/wechat_id,用 avatar 作为唯一标识
const hasId = player?.userid || player?.wechat_id || player?.openid || player?.user_id;
const avatar = player?.avatar || '';
const nickname = player?.nickname || '虚位以待';
const isRealPlayer = nickname && nickname !== '-' && nickname !== '虚位以待';
const wechat_id = hasId || (isRealPlayer && avatar ? `avt:${avatar}` : `empty-${index}`);
return {
telephone: player?.telephone ?? '', telephone: player?.telephone ?? '',
userid: player?.userid ?? '', userid: hasId || (isRealPlayer && avatar ? `avt:${avatar}` : ''),
wechat_id: player?.wechat_id || `empty-${index}`, wechat_id,
nickname: player?.nickname || '虚位以待', nickname,
avatar: player?.avatar || '', avatar,
score: player?.score ?? '-', score: player?.score ?? '-',
}) };
}
const seedRankPlayersFromLoading = () => { const seedRankPlayersFromLoading = () => {
console.log("[Game4] seedRankPlayersFromLoading 开始,loadingPlayers:", loadingPlayers.value.length, JSON.stringify(loadingPlayers.value.slice(0, 3)));
rankPlayers.value = Array.from( rankPlayers.value = Array.from(
{ length: RANK_LIMIT }, { length: RANK_LIMIT },
(_, index) => { (_, index) => {
const player = loadingPlayers.value[index] const player = loadingPlayers.value[index]
if (!player?.userid && !player?.wechat_id) { if (!player?.userid && !player?.wechat_id) {
console.log("[Game4] seedRankPlayersFromLoading index:", index, "无 userid/wechat_id,判定为空占位");
return emptyRankPlayer(index) return emptyRankPlayer(index)
} }
console.log("[Game4] seedRankPlayersFromLoading index:", index, "有玩家数据:", JSON.stringify(player));
return playerToRankPlayer(player, index) return playerToRankPlayer(player, index)
}, },
) )
console.log("[Game4] seedRankPlayersFromLoading 完成,rankPlayers:", rankPlayers.value.length, JSON.stringify(rankPlayers.value.slice(0, 3)));
} }
const resetRoundState = () => { const resetRoundState = () => {
...@@ -122,6 +139,8 @@ const gameId = 'game4' ...@@ -122,6 +139,8 @@ const gameId = 'game4'
const { startGame, createRoom, backRoom, closeRoom } = useAdminGameSocket({ const { startGame, createRoom, backRoom, closeRoom } = useAdminGameSocket({
gameId, gameId,
onAny: (evt, payload) => { onAny: (evt, payload) => {
console.log("[Game4 WebSocket] 🔥 onAny 触发 - event:", evt, "payload:", payload);
const data = payload?.data ?? payload; const data = payload?.data ?? payload;
// 调试日志:打印 WebSocket 原始数据 // 调试日志:打印 WebSocket 原始数据
...@@ -133,7 +152,10 @@ const { startGame, createRoom, backRoom, closeRoom } = useAdminGameSocket({ ...@@ -133,7 +152,10 @@ const { startGame, createRoom, backRoom, closeRoom } = useAdminGameSocket({
rawPayload: payload, rawPayload: payload,
}); });
if (!Array.isArray(data)) return; if (!Array.isArray(data)) {
console.log("[Game4 WebSocket] ⚠️ data 不是数组,跳过处理");
return;
}
const boosts: Record<string, number> = {}; const boosts: Record<string, number> = {};
let hasBoost = false; let hasBoost = false;
...@@ -158,6 +180,7 @@ const { startGame, createRoom, backRoom, closeRoom } = useAdminGameSocket({ ...@@ -158,6 +180,7 @@ const { startGame, createRoom, backRoom, closeRoom } = useAdminGameSocket({
} }
}, },
onRoomState: (data: any) => { onRoomState: (data: any) => {
console.log("[Game4] onRoomState 触发,data:", JSON.stringify(data));
if (Array.isArray(data?.list)) { if (Array.isArray(data?.list)) {
renderPlayers(data) renderPlayers(data)
} }
...@@ -173,7 +196,9 @@ const { startGame, createRoom, backRoom, closeRoom } = useAdminGameSocket({ ...@@ -173,7 +196,9 @@ const { startGame, createRoom, backRoom, closeRoom } = useAdminGameSocket({
gotoLoading() gotoLoading()
break break
case 2: case 2:
console.log("[Game4] status=2,准备进入 rank1,loadingPlayers:", loadingPlayers.value.length);
seedRankPlayersFromLoading() seedRankPlayersFromLoading()
console.log("[Game4] seedRankPlayersFromLoading 后,rankPlayers:", rankPlayers.value.length, JSON.stringify(rankPlayers.value.slice(0, 3)));
screen.value = 'rank1' screen.value = 'rank1'
break break
case 3: case 3:
......
...@@ -165,18 +165,34 @@ const gameStarted = ref(false); ...@@ -165,18 +165,34 @@ const gameStarted = ref(false);
const LANE_POSITIONS = [0, 108, 228, 338, 448]; const LANE_POSITIONS = [0, 108, 228, 338, 448];
const updateHorses = (players: Player[]) => { const updateHorses = (players: Player[]) => {
const validPlayers = players.filter( console.log("[Rank1View] updateHorses 被调用,players:", players?.length, JSON.stringify(players?.slice(0, 3)));
(p) => p.nickname !== "虚位以待" && !p.wechat_id?.startsWith("empty-"),
); const validPlayers = players.filter((p) => {
// 昵称必须是真实玩家
if (!p.nickname || p.nickname === "虚位以待" || p.nickname === "-") return false;
// wechat_id 不能是空占位
if (p.wechat_id && String(p.wechat_id).startsWith("empty-")) return false;
// 有 userid/wechat_id 或者有 avatar,都认为是真实玩家
if (p.userid || p.wechat_id || p.avatar) return true;
return false;
});
if (validPlayers.length === 0) return; console.log("[Rank1View] 有效玩家数:", validPlayers.length, validPlayers.map(p => ({ nickname: p.nickname, userid: p.userid, wechat_id: p.wechat_id, avatar: p.avatar })));
if (validPlayers.length === 0) {
console.log("[Rank1View] ⚠️ 无有效玩家,不生成马匹");
return;
}
// 保留已存在的 xPercent 和 boost,避免新玩家列表覆盖进度 // 保留已存在的 xPercent 和 boost,避免新玩家列表覆盖进度
const existingMap = new Map(horses.value.map((h) => [h.id, h])); const existingMap = new Map(horses.value.map((h) => [h.id, h]));
horses.value = validPlayers.map((player, index) => { horses.value = validPlayers.map((player, index) => {
// WebSocket 数据无 userid/wechat_id,用 avatar 作为稳定标识 // WebSocket 数据无 userid/wechat_id,用 avatar 作为稳定标识
const id = player.userid || player.wechat_id || player.avatar || `horse-${index}`; const id = player.userid || player.wechat_id || (player.avatar ? `avt:${player.avatar}` : `horse-${index}`);
const existing = existingMap.get(id); const existing = existingMap.get(id);
const horseType = HORSE_TYPES[index % HORSE_TYPES.length]!; const horseType = HORSE_TYPES[index % HORSE_TYPES.length]!;
return { return {
...@@ -192,6 +208,8 @@ const updateHorses = (players: Player[]) => { ...@@ -192,6 +208,8 @@ const updateHorses = (players: Player[]) => {
frameTimer: existing?.frameTimer ?? 0, frameTimer: existing?.frameTimer ?? 0,
}; };
}); });
console.log("[Rank1View] ✅ 生成马匹数:", horses.value.length, horses.value.map(h => ({ id: h.id, nickname: h.nickname, startY: h.startY })));
}; };
const mockAvatars = [ const mockAvatars = [
...@@ -221,6 +239,7 @@ const mockHorses = () => { ...@@ -221,6 +239,7 @@ const mockHorses = () => {
watch( watch(
() => props.rankList, () => props.rankList,
(players) => { (players) => {
console.log("[Rank1View] watch rankList 触发,players:", players?.length, JSON.stringify(players?.slice(0, 2)));
if (players && players.length > 0) { if (players && players.length > 0) {
updateHorses(players); updateHorses(players);
// 检测积分增长 → 触发瞬时加速脉冲 // 检测积分增长 → 触发瞬时加速脉冲
...@@ -409,6 +428,9 @@ const stopGame = () => { ...@@ -409,6 +428,9 @@ const stopGame = () => {
}; };
const startIntro = async () => { const startIntro = async () => {
console.log("[Rank1View] startIntro 开始,当前 rankList:", props.rankList?.length, JSON.stringify(props.rankList?.slice(0, 2)));
console.log("[Rank1View] 当前 horses 数量:", horses.value.length);
// 本地模拟已关闭,如需开启请取消以下注释 // 本地模拟已关闭,如需开启请取消以下注释
// if ($is_local_mode()) { // if ($is_local_mode()) {
// mockHorses(); // mockHorses();
...@@ -424,6 +446,8 @@ const startIntro = async () => { ...@@ -424,6 +446,8 @@ const startIntro = async () => {
const countdownPromise = designStage.value?.startCountdown(3, 60); const countdownPromise = designStage.value?.startCountdown(3, 60);
await new Promise((r) => setTimeout(r, 3500)); await new Promise((r) => setTimeout(r, 3500));
console.log("[Rank1View] 倒计时结束,准备启动游戏,当前 horses:", horses.value.length, horses.value.map(h => h.nickname));
gameStarted.value = true; gameStarted.value = true;
isGameRunning.value = true; isGameRunning.value = true;
......
...@@ -79,14 +79,23 @@ const updateRankPlayers = (data: any) => { ...@@ -79,14 +79,23 @@ const updateRankPlayers = (data: any) => {
) )
} }
const playerToRankPlayer = (player: any, index: number): Player => ({ const playerToRankPlayer = (player: any, index: number): Player => {
// WebSocket 数据可能没有 userid/wechat_id,用 avatar 作为唯一标识
const hasId = player?.userid || player?.wechat_id || player?.openid || player?.user_id;
const avatar = player?.avatar || '';
const nickname = player?.nickname || '虚位以待';
const isRealPlayer = nickname && nickname !== '-' && nickname !== '虚位以待';
const wechat_id = hasId || (isRealPlayer && avatar ? `avt:${avatar}` : `empty-${index}`);
return {
telephone: player?.telephone ?? '', telephone: player?.telephone ?? '',
userid: player?.userid ?? '', userid: hasId || (isRealPlayer && avatar ? `avt:${avatar}` : ''),
wechat_id: player?.wechat_id || `empty-${index}`, wechat_id,
nickname: player?.nickname || '虚位以待', nickname,
avatar: player?.avatar || '', avatar,
score: player?.score ?? '-', score: player?.score ?? '-',
}) };
}
const seedRankPlayersFromLoading = () => { const seedRankPlayersFromLoading = () => {
rankPlayers.value = Array.from( rankPlayers.value = Array.from(
...@@ -158,18 +167,21 @@ function handleRoomState(data: any) { ...@@ -158,18 +167,21 @@ function handleRoomState(data: any) {
const { startGame, createRoom, closeRoom, backRoom } = useAdminGameSocket({ const { startGame, createRoom, closeRoom, backRoom } = useAdminGameSocket({
gameId: 'game5', gameId: 'game5',
onAny: (evt, payload) => {
console.log("[Game5 WebSocket] 🔥 onAny 触发 - event:", evt, "payload:", JSON.stringify(payload));
},
onRoomState: handleRoomState, onRoomState: handleRoomState,
onRoomJoin: (data) => { onRoomJoin: (data) => {
console.log('[WebSocket] 玩家加入房间 - 数据:', JSON.stringify(data)) console.log('[Game5] onRoomJoin 触发 - 数据:', JSON.stringify(data))
renderPlayers(data) renderPlayers(data)
gotoLoading() gotoLoading()
}, },
onGameStart: () => { onGameStart: () => {
console.log('[WebSocket] 游戏开始!') console.log('[Game5] 游戏开始!')
gotoRank1WithIntro() gotoRank1WithIntro()
}, },
onRoomRank: (data) => { onRoomRank: (data) => {
console.log('[WebSocket] 排名更新 - 数据:', JSON.stringify(data)) console.log('[Game5] onRoomRank 触发 - 数据:', JSON.stringify(data))
updateRankPlayers(data) updateRankPlayers(data)
}, },
onRelogin: async () => { onRelogin: async () => {
......
...@@ -75,8 +75,18 @@ const emptyPlayer = (index: number): Player => ({ ...@@ -75,8 +75,18 @@ const emptyPlayer = (index: number): Player => ({
const list = ref<Player[]>( const list = ref<Player[]>(
Array.from({ length: RANK_LIMIT }, (_, index) => emptyPlayer(index)), Array.from({ length: RANK_LIMIT }, (_, index) => emptyPlayer(index)),
); );
const playerKey = (player: Player, index = 0) => const playerKey = (player: Player, index = 0) => {
player.userid || player.wechat_id || `empty-${index}`; // 优先使用 userid/wechat_id,没有则用 avatar 作为唯一标识
const id = player.userid || player.wechat_id;
if (id && !String(id).startsWith('empty-')) return String(id);
// 如果有头像且昵称有效,用 avatar 作为唯一标识
if (player.avatar && player.nickname && player.nickname !== '-' && player.nickname !== '虚位以待') {
return `avt:${player.avatar}`;
}
return `empty-${index}`;
};
// ========== 排名更新 ========== // ========== 排名更新 ==========
const updateRankList = (rankList: Player[]) => { const updateRankList = (rankList: Player[]) => {
...@@ -109,8 +119,9 @@ const updateRankList = (rankList: Player[]) => { ...@@ -109,8 +119,9 @@ const updateRankList = (rankList: Player[]) => {
watch( watch(
() => props.rankList, () => props.rankList,
(rankList) => { (rankList) => {
console.log('[Game5 Rank1View] watch rankList 触发,rankList:', rankList?.length, JSON.stringify(rankList?.slice(0, 3)));
if (rankList && rankList.length > 0) { if (rankList && rankList.length > 0) {
console.log('[Rank1View] 排名列表更新 - 数据:', JSON.stringify(rankList.map(p => ({ nickname: p.nickname, score: p.score })))) console.log('[Game5 Rank1View] 排名列表更新 - 数据:', JSON.stringify(rankList.map(p => ({ nickname: p.nickname, score: p.score, userid: p.userid, wechat_id: p.wechat_id }))))
updateRankList(rankList); updateRankList(rankList);
} }
......
...@@ -75,7 +75,18 @@ const emptyPlayer = (index: number): Player => ({ ...@@ -75,7 +75,18 @@ const emptyPlayer = (index: number): Player => ({
}); });
const list = ref<Player[]>(Array.from({ length: RANK_LIMIT }, (_, index) => emptyPlayer(index))); const list = ref<Player[]>(Array.from({ length: RANK_LIMIT }, (_, index) => emptyPlayer(index)));
const playerKey = (player: Player, index = 0) => player.userid || player.wechat_id || `empty-${index}`; const playerKey = (player: Player, index = 0) => {
// 优先使用 userid/wechat_id,没有则用 avatar 作为唯一标识
const id = player.userid || player.wechat_id;
if (id && !String(id).startsWith('empty-')) return String(id);
// 如果有头像且昵称有效,用 avatar 作为唯一标识
if (player.avatar && player.nickname && player.nickname !== '-' && player.nickname !== '虚位以待') {
return `avt:${player.avatar}`;
}
return `empty-${index}`;
};
const mockRankStep = ref(0); const mockRankStep = ref(0);
type MoleKind = "land" | "mole" | "rabbit"; type MoleKind = "land" | "mole" | "rabbit";
type MolePhase = "land" | "show" | "hide"; type MolePhase = "land" | "show" | "hide";
......
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