329 lines
8.0 KiB
Vue
329 lines
8.0 KiB
Vue
<script setup>
|
||
import { ref, computed, onMounted, onBeforeUnmount } from "vue";
|
||
import HeaderProgress from "@/components/HeaderProgress.vue";
|
||
import Avatar from "@/components/Avatar.vue";
|
||
|
||
import useStore from "@/store";
|
||
import { storeToRefs } from "pinia";
|
||
const store = useStore();
|
||
const { user, game } = storeToRefs(store);
|
||
|
||
const currentPage = computed(() => {
|
||
const pages = getCurrentPages();
|
||
return pages[pages.length - 1].route;
|
||
});
|
||
|
||
const props = defineProps({
|
||
title: {
|
||
type: String,
|
||
default: "",
|
||
},
|
||
onBack: {
|
||
type: Function,
|
||
default: null,
|
||
},
|
||
whiteBackArrow: {
|
||
type: Boolean,
|
||
default: true,
|
||
},
|
||
});
|
||
|
||
const onClick = () => {
|
||
if (props.onBack) {
|
||
props.onBack();
|
||
} else {
|
||
const pages = getCurrentPages();
|
||
if (pages.length > 1) {
|
||
uni.navigateBack();
|
||
} else {
|
||
uni.redirectTo({
|
||
url: "/pages/index",
|
||
});
|
||
}
|
||
}
|
||
};
|
||
|
||
const toUserPage = () => {
|
||
uni.navigateTo({
|
||
url: "/pages/user",
|
||
});
|
||
};
|
||
|
||
const signin = () => {
|
||
if (!user.value.id) {
|
||
uni.$emit("point-book-signin");
|
||
}
|
||
};
|
||
|
||
const loading = ref(false);
|
||
const pointBook = ref(null);
|
||
const heat = ref(0);
|
||
/** 房间号按钮动态定位样式(position: fixed,根据胶囊真实位置计算,脱离 flex 流避免挤压标题) */
|
||
const battleRoomBtnStyle = ref({});
|
||
|
||
const updateLoading = (value) => {
|
||
loading.value = value;
|
||
};
|
||
|
||
const updateHot = (value) => {
|
||
heat.value = value;
|
||
};
|
||
|
||
onMounted(() => {
|
||
const pages = getCurrentPages();
|
||
const currentPage = pages[pages.length - 1];
|
||
if (
|
||
currentPage.route === "pages/point-book-edit" ||
|
||
currentPage.route === "pages/point-book-detail"
|
||
) {
|
||
pointBook.value = uni.getStorageSync("point-book");
|
||
if (!pointBook.value) {
|
||
pointBook.value = uni.getStorageSync("last-point-book");
|
||
}
|
||
}
|
||
// 仅在对战房间页获取胶囊位置,按钮用 fixed 定位精确贴靠胶囊左侧(脱离 flex 流,不挤压标题)
|
||
if (currentPage.route === "pages/battle-room") {
|
||
try {
|
||
const menuButtonRect = uni.getMenuButtonBoundingClientRect();
|
||
const { windowWidth } = uni.getSystemInfoSync();
|
||
battleRoomBtnStyle.value = {
|
||
// 按钮右边缘距视口右侧 = 屏幕宽 - 胶囊左边缘 + 4px 安全间隙
|
||
right: (windowWidth - menuButtonRect.left + 4) + "px",
|
||
// 垂直位置与胶囊顶部对齐
|
||
top: menuButtonRect.top + "px",
|
||
// 高度与胶囊一致,视觉融合
|
||
height: menuButtonRect.height + "px",
|
||
};
|
||
} catch (e) {
|
||
// 获取失败时使用 CSS 兜底定位(28vw + 4px 作为 right,8px 作为 top)
|
||
}
|
||
}
|
||
uni.$on("update-hot", updateHot);
|
||
});
|
||
onBeforeUnmount(() => {
|
||
uni.$off("update-hot", updateHot);
|
||
});
|
||
</script>
|
||
|
||
<template>
|
||
<view class="container">
|
||
<view class="back-btn" @click="onClick">
|
||
<image v-if="whiteBackArrow" src="../static/back.png" mode="widthFix" />
|
||
<image
|
||
v-if="!whiteBackArrow"
|
||
src="../static/back-black.png"
|
||
mode="widthFix"
|
||
/>
|
||
</view>
|
||
<view :style="{ color: whiteBackArrow ? '#fff' : '#000' }">
|
||
<view
|
||
v-if="currentPage === 'pages/point-book'"
|
||
class="user-header"
|
||
@click="signin"
|
||
>
|
||
<block v-if="user.id">
|
||
<Avatar
|
||
:src="user.avatar"
|
||
:onClick="toUserPage"
|
||
:size="40"
|
||
borderColor="#333"
|
||
/>
|
||
<text class="truncate">{{ user.nickName }}</text>
|
||
<image
|
||
v-if="heat"
|
||
:src="`../static/hot${heat}.png`"
|
||
mode="widthFix"
|
||
/>
|
||
</block>
|
||
<block v-else>
|
||
<image src="../static/user-icon.png" mode="widthFix" />
|
||
<text>新来的弓箭手你好呀~</text>
|
||
</block>
|
||
</view>
|
||
<block
|
||
v-if="
|
||
'-箭前准备-感知距离-小试牛刀'.indexOf(title) === -1 ||
|
||
'-箭前准备-感知距离-小试牛刀'.indexOf(title) === 11
|
||
"
|
||
>
|
||
<text>{{ title }}</text>
|
||
</block>
|
||
<block
|
||
v-if="
|
||
title &&
|
||
'-箭前准备-感知距离-小试牛刀'.indexOf(title) !== -1 &&
|
||
'-箭前准备-感知距离-小试牛刀'.indexOf(title) !== 11
|
||
"
|
||
>
|
||
<view class="first-try-steps">
|
||
<text :class="title === '-箭前准备' ? 'current-step' : ''">箭前准备</text>
|
||
<text>-</text>
|
||
<text :class="title === '-感知距离' ? 'current-step' : ''"
|
||
>感知距离</text
|
||
>
|
||
<text>-</text>
|
||
<text :class="title === '-小试牛刀' ? 'current-step' : ''"
|
||
>小试牛刀</text
|
||
>
|
||
</view>
|
||
</block>
|
||
</view>
|
||
<view v-if="pointBook" class="point-book-info">
|
||
<text>{{ pointBook.bowType.name }}</text>
|
||
<text>{{ pointBook.distance }} 米</text>
|
||
<text
|
||
>{{
|
||
pointBook.bowtargetType.name.substring(
|
||
0,
|
||
pointBook.bowtargetType.name.length - 3
|
||
)
|
||
}}
|
||
{{
|
||
pointBook.bowtargetType.name.substring(
|
||
pointBook.bowtargetType.name.length - 3
|
||
)
|
||
}}</text
|
||
>
|
||
</view>
|
||
<view
|
||
v-if="
|
||
currentPage === 'pages/team-battle' ||
|
||
currentPage === 'pages/team-battle/index'
|
||
"
|
||
class="battle-progress"
|
||
>
|
||
<HeaderProgress />
|
||
</view>
|
||
<!-- 对战房间:整个胶囊为分享按钮,房号从 Store 读取;fixed 定位紧靠系统胶囊左侧 -->
|
||
<button
|
||
v-if="currentPage === 'pages/battle-room' && game.roomNumber"
|
||
open-type="share"
|
||
hover-class="none"
|
||
class="battle-room-number"
|
||
:style="battleRoomBtnStyle"
|
||
>
|
||
<text class="battle-room-number__text">房号: {{ game.roomNumber }}</text>
|
||
<image src="../static/share2.png" mode="widthFix" class="battle-room-number__icon" />
|
||
</button>
|
||
</view>
|
||
</template>
|
||
|
||
<style scoped>
|
||
.container {
|
||
display: flex;
|
||
justify-content: flex-start;
|
||
align-items: center;
|
||
width: 72vw;
|
||
height: 50px;
|
||
/* margin-top: var(--status-bar-height); */
|
||
padding-left: 15px;
|
||
}
|
||
.container > view:nth-child(2) {
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
}
|
||
.back-btn {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
.back-btn > image {
|
||
width: 22px;
|
||
height: 22px;
|
||
margin-right: 10px;
|
||
}
|
||
.first-try-steps {
|
||
display: flex;
|
||
align-items: center;
|
||
color: #fff6;
|
||
font-size: 14px;
|
||
}
|
||
.first-try-steps > text {
|
||
transition: all 0.3s ease;
|
||
}
|
||
.first-try-steps > text:nth-child(2),
|
||
.first-try-steps > text:nth-child(4) {
|
||
margin: 0 5px;
|
||
}
|
||
.current-step {
|
||
font-size: 16px;
|
||
color: #fff;
|
||
}
|
||
.point-book-info {
|
||
color: #333;
|
||
position: fixed;
|
||
width: 60%;
|
||
left: 20%;
|
||
display: flex;
|
||
justify-content: center;
|
||
}
|
||
.point-book-info > text {
|
||
border-radius: 6px;
|
||
background-color: #fff;
|
||
font-size: 10px;
|
||
padding: 5px 10px;
|
||
margin: 3px;
|
||
}
|
||
.battle-progress {
|
||
position: fixed;
|
||
width: 60%;
|
||
left: 20%;
|
||
display: flex;
|
||
justify-content: center;
|
||
}
|
||
.user-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-start;
|
||
}
|
||
.user-header > image:first-child {
|
||
width: 40px;
|
||
height: 40px;
|
||
border-radius: 50%;
|
||
border: 2rpx solid #333;
|
||
}
|
||
.user-header > image:last-child {
|
||
width: 36rpx;
|
||
height: 36rpx;
|
||
}
|
||
.user-header > text:nth-child(2) {
|
||
font-weight: 500;
|
||
font-size: 30rpx;
|
||
color: #333333;
|
||
margin: 0 20rpx;
|
||
max-width: 300rpx;
|
||
}
|
||
/* 对战房间:整个胶囊作为分享按钮,fixed 定位脱离 flex 流,紧贴系统胶囊左侧 */
|
||
.battle-room-number {
|
||
position: fixed;
|
||
/* 兜底定位(JS 获取胶囊位置失败时生效):约 28vw 对应胶囊区域左边缘 */
|
||
right: calc(28vw + 4px);
|
||
top: 8px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 240rpx;
|
||
height: 64rpx;
|
||
background: rgba(0, 0, 0, 0.15);
|
||
border-radius: 96rpx;
|
||
border: 1rpx solid #5b5758;
|
||
padding: 0;
|
||
}
|
||
/* 重置 button 默认边框 */
|
||
.battle-room-number::after {
|
||
border: none;
|
||
}
|
||
.battle-room-number__text {
|
||
width: 156rpx;
|
||
height: 28rpx;
|
||
font-weight: 400;
|
||
font-size: 20rpx;
|
||
color: #ffffff;
|
||
text-align: center;
|
||
line-height: 28rpx;
|
||
}
|
||
.battle-room-number__icon {
|
||
width: 25rpx;
|
||
height: 26rpx;
|
||
}
|
||
</style>
|