diff --git a/src/App.vue b/src/App.vue index c852548..6b3b1f0 100644 --- a/src/App.vue +++ b/src/App.vue @@ -250,6 +250,69 @@ text-overflow: ellipsis; } + .member-nickname { + position: relative; + display: inline-flex; + max-width: 100%; + overflow: hidden; + } + + .member-nickname__text, + .member-nickname__shine { + display: block; + max-width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .member-nickname--vip .member-nickname__text { + color: #E7BA80; + } + + .member-nickname--svip .member-nickname__text { + background: linear-gradient(90deg, #ffb86c, #ff4fd8, #7c5cff, #35d6ff); + -webkit-background-clip: text; + background-clip: text; + color: transparent; + } + + .member-nickname__shine { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + background: linear-gradient( + 110deg, + transparent 0%, + transparent 38%, + rgba(255, 255, 255, 0.15) 45%, + rgba(255, 255, 255, 1) 50%, + rgba(255, 255, 255, 0.15) 55%, + transparent 62%, + transparent 100% + ); + background-size: 220% 100%; + background-position: 120% 0; + -webkit-background-clip: text; + background-clip: text; + color: transparent; + pointer-events: none; + animation: memberNicknameShine 3.5s infinite ease-in-out; + } + + @keyframes memberNicknameShine { + 0%, + 50% { + background-position: 120% 0; + } + + 100% { + background-position: -200% 0; + } + } + .modal { height: 100%; display: flex; diff --git a/src/components/AppBackground.vue b/src/components/AppBackground.vue index 32bfcb7..00feb51 100644 --- a/src/components/AppBackground.vue +++ b/src/components/AppBackground.vue @@ -60,7 +60,7 @@ const props = defineProps({ diff --git a/src/components/BackToGame.vue b/src/components/BackToGame.vue index b5a509c..5297d74 100644 --- a/src/components/BackToGame.vue +++ b/src/components/BackToGame.vue @@ -18,12 +18,14 @@ const props = defineProps({ }, }); const loading = ref(false); +const navigating = ref(false); /** 统一获取当前环境 token,用于守卫:无有效 token 时不发起接口请求 */ const getToken = () => uni.getStorageSync(`${uni.getAccountInfoSync().miniProgram.envVersion}_token`); onShow(async () => { + navigating.value = false; if (user.value.id && getToken()) { setTimeout(async () => { const state = await getUserGameState(); @@ -45,28 +47,35 @@ watch( } ); +const navigateOnce = (url) => + new Promise((resolve, reject) => { + navigating.value = true; + uni.navigateTo({ + url, + success: resolve, + fail: (error) => { + navigating.value = false; + reject(error); + }, + }); + }); + const onClick = debounce(async () => { - if (loading.value) return; + if (loading.value || navigating.value) return; try { loading.value = true; const result = await getBattleAPI(); if (result && result.matchId) { await uni.$checkAudio(); if (result.mode <= 3) { - uni.navigateTo({ - url: `/pages/team-battle/index?battleId=${result.matchId}`, - }); + await navigateOnce(`/pages/team-battle/index?battleId=${result.matchId}`); } else { - uni.navigateTo({ - url: `/pages/melee-battle?battleId=${result.matchId}`, - }); + await navigateOnce(`/pages/melee-battle?battleId=${result.matchId}`); } return; } if (game.value.roomID) { - uni.navigateTo({ - url: "/pages/battle-room?roomNumber=" + game.value.roomID, - }); + await navigateOnce("/pages/battle-room?roomNumber=" + game.value.roomID); } else { updateGame(false, ""); } diff --git a/src/components/BattleHeader.vue b/src/components/BattleHeader.vue index b12d84f..1ade377 100644 --- a/src/components/BattleHeader.vue +++ b/src/components/BattleHeader.vue @@ -27,6 +27,14 @@ defineProps({ default: true, }, }); + +const getMemberNicknameClass = (player = {}) => [ + "member-nickname", + player.vip === true && player.sVip !== true ? "member-nickname--vip" : "", + player.sVip === true ? "member-nickname--svip" : "", +]; + +const isMember = (player = {}) => player.vip === true || player.sVip === true;