Files
shoot-miniprograms/src/pages/team-battle/components/HeaderProgress.vue

84 lines
2.5 KiB
Vue

<script setup>
import { ref, watch, onMounted, onBeforeUnmount } from "vue";
import audioManager from "@/audioManager";
import useStore from "@/store";
const store = useStore();
// 私有 HeaderProgress 只负责展示提示/箭数和静音开关。
// 报靶、轮到谁射箭、比赛结束等语音统一由 team-battle 页面队列播放,避免重复播报。
const tips = ref("");
const sound = ref(true);
const currentShot = ref(0);
const totalShot = ref(0);
const updateSound = () => {
sound.value = !sound.value;
audioManager.setMuted(!sound.value);
};
const onUpdateTips = (newVal) => {
// 兼容页面通过 uni.$emit("update-tips") 触发的即时刷新。
tips.value = newVal;
};
// 监听 Pinia store 中 totalShot 变化,用于比赛恢复时同步箭数(替代 uni.$emit 避免时序问题)
// 使用 immediate: true 确保组件创建时立即读取 store 当前值(解决重入时 totalShot 值不变 watch 不触发的问题)
watch(
() => [store.game.currentShot, store.game.totalShot],
([newCurrentShot, newTotalShot]) => {
currentShot.value = newCurrentShot || 0;
totalShot.value = newTotalShot || 0;
},
{ immediate: true }
);
// 监听 Pinia store 中 tips 变化,用于比赛恢复时同步提示文案(替代 uni.$emit 避免时序问题)
// 使用 immediate: true 确保组件创建时立即读取 store 当前值(解决 onShow 早于 onMounted 导致 uni.$emit 事件丢失的问题)
// 注意:使用 != null 而非 if(newVal),确保空字符串 "" 也能触发清空(避免重新开赛时旧文案残留)
watch(() => store.game.tips, (newVal) => {
if (newVal != null) {
tips.value = newVal;
}
}, { immediate: true });
onMounted(() => {
uni.$on("update-tips", onUpdateTips);
});
onBeforeUnmount(() => {
uni.$off("update-tips", onUpdateTips);
});
</script>
<template>
<view class="container">
<text>{{ (tips || "").replace(/你/g, "").replace(/重回/g, "") }}</text>
<text v-if="totalShot > 0"> ({{ currentShot }}/{{ totalShot }}) </text>
<button v-if="!!tips" hover-class="none" @click="updateSound">
<image :src="`../../../static/sound${sound ? '' : '-off'}-yellow.png`" mode="widthFix" />
</button>
</view>
</template>
<style scoped>
.container {
width: 50vw;
color: #fed847;
display: flex;
align-items: center;
justify-content: center;
font-weight: 500;
}
.container>button:last-child {
width: 36px;
height: 36px;
}
.container>button:last-child>image {
width: 36px;
min-height: 36px;
}
</style>