5 Commits

8 changed files with 105 additions and 39 deletions

View File

@@ -6,8 +6,7 @@ try {
switch (envVersion) {
case "develop": // 开发版
BASE_URL = "http://localhost:8000/api/shoot";
// BASE_URL = "https://apitest.shelingxingqiu.com/api/shoot";
BASE_URL = "https://apitest.shelingxingqiu.com/api/shoot";
break;
case "trial": // 体验版
BASE_URL = "https://apitest.shelingxingqiu.com/api/shoot";

View File

@@ -26,20 +26,21 @@ defineProps({
.container {
display: flex;
align-items: center;
padding: 0 15px;
padding: 0 26rpx 0 28rpx;
margin-bottom: 14rpx;
width: clac(100% - 30px);
width: clac(100% - 54rpx);
}
.container .shooter2 {
width: 150rpx;
height: 162rpx;
display: block;
width: 133rpx;
height: 144rpx;
}
.container .bg-box {
color: #fff;
font-size: 28rpx;
position: relative;
flex: 1;
min-height: 55px;
height: 128rpx;
display: flex;
align-items: center;
justify-content: center;

View File

@@ -6,7 +6,7 @@ import Avatar from "@/components/Avatar.vue";
import useStore from "@/store";
import { storeToRefs } from "pinia";
const store = useStore();
const { user } = storeToRefs(store);
const { user, game } = storeToRefs(store);
const currentPage = computed(() => {
const pages = getCurrentPages();
@@ -59,8 +59,6 @@ const loading = ref(false);
const pointBook = ref(null);
const showProgress = ref(false);
const heat = ref(0);
/** 当前对战房间的房号,由 battle-room 页面通过 uni.$emit 传入 */
const battleRoomNumber = ref("");
const updateLoading = (value) => {
loading.value = value;
@@ -70,14 +68,6 @@ const updateHot = (value) => {
heat.value = value;
};
/**
* 接收 battle-room 页面发出的房间信息,更新房号展示
* @param {{ roomNumber: string }} info
*/
const updateBattleRoomInfo = (info) => {
battleRoomNumber.value = info.roomNumber || "";
};
onMounted(() => {
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
@@ -94,11 +84,9 @@ onMounted(() => {
showProgress.value = true;
}
uni.$on("update-hot", updateHot);
uni.$on("battle-room-info", updateBattleRoomInfo);
});
onBeforeUnmount(() => {
uni.$off("update-hot", updateHot);
uni.$off("battle-room-info", updateBattleRoomInfo);
});
</script>
@@ -185,14 +173,14 @@ onBeforeUnmount(() => {
<view v-if="showProgress" class="battle-progress">
<HeaderProgress />
</view>
<!-- 对战房间:整个胶囊为分享按钮,点击任意区域均可触发分享 -->
<!-- 对战房间:整个胶囊为分享按钮,房号从 Store 读取 -->
<button
v-if="currentPage === 'pages/battle-room' && battleRoomNumber"
v-if="currentPage === 'pages/battle-room' && game.roomNumber"
open-type="share"
hover-class="none"
class="battle-room-number"
>
<text class="battle-room-number__text">房号: {{ battleRoomNumber }}</text>
<text class="battle-room-number__text">房号: {{ game.roomNumber }}</text>
<image src="../static/share2.png" mode="widthFix" class="battle-room-number__icon" />
</button>
</view>
@@ -285,7 +273,7 @@ onBeforeUnmount(() => {
/* 对战房间:整个胶囊作为分享按钮,靠右对齐 */
.battle-room-number {
margin-left: auto;
margin-right: 10rpx;
margin-right: 20rpx;
display: flex;
align-items: center;
justify-content: center;

View File

@@ -117,7 +117,7 @@ const checkBowData = () => {
}deg)`,
}"
>
<view v-if="data.mvp && data.mvp[0].totalRings">
<view v-if="data.mvp && data.mvp.totalRings">
<image src="../static/title-mvp.png" mode="widthFix" />
<text
>斩获<text
@@ -127,7 +127,7 @@ const checkBowData = () => {
margin: '0 3px',
fontWeight: '600',
}"
>{{ data.mvp[0].totalRings }}</text
>{{ data.mvp.totalRings }}</text
></text
>
</view>

View File

@@ -42,16 +42,40 @@ const battleTitle = computed(() => {
return `${half}v${half}对抗赛`;
});
/** 靶纸尺寸cm由 URL 参数或 API 返回的 targetType 字段填充 */
const targetSize = ref(0);
/**
* 根据 targetSize 动态生成靶纸尺寸文本,如"40cm"
* 数据未就绪时显示 "--";数据来源:创建者取 URL 参数 target加入者取 API 返回的 targetType
*/
const targetSizeLabel = computed(() =>
targetSize.value ? `${targetSize.value}cm` : '--'
);
const ready = ref(false);
const allReady = ref(false);
const timer = ref(null);
const goBattle = ref(false);
/**
* 从服务端刷新当前房间数据,更新成员列表、准备状态等信息
* 仅在 roomNumber 有效且房间未开始时执行
*/
async function refreshRoomData() {
if (!roomNumber.value) return;
const result = await getRoomAPI(roomNumber.value);
if (result.started) return;
room.value = result;
// 加入者通过 API 返回的 targetType 字段同步靶纸尺寸,并持久化到本地缓存
if (result.targetType) {
targetSize.value = result.targetType;
uni.setStorageSync(`targetSize_${roomNumber.value}`, result.targetType);
} else if (targetSize.value === 0) {
// API 无该字段时,从本地缓存兜底(如"返回房间"场景)
const stored = uni.getStorageSync(`targetSize_${roomNumber.value}`);
if (stored) targetSize.value = stored;
}
owner.value = {};
opponent.value = {};
const members = result.members || [];
@@ -109,9 +133,6 @@ async function refreshRoomData() {
}
if (timer.value) clearInterval(timer.value);
// timer.value = setTimeout(refreshRoomData, 2000);
// 通知 Header 组件更新房号展示
uni.$emit("battle-room-info", { roomNumber: roomNumber.value });
}
const startGame = async () => {
@@ -240,27 +261,64 @@ const canClick = computed(() => {
return true;
});
/**
* 根据对战类型和人数动态生成分享文案
* 1v1 / 默认 → "星球论箭,来一决高下敢否?"
* 2v2 → "2v2对抗赛是兄弟来助我一把!"
* 3v3 → "3v3对抗赛来了马上发车!"
* 乱斗 → "热血乱斗赛,敢来争锋?"
*/
const shareTitle = computed(() => {
const { battleType, count } = room.value;
if (battleType === 2) return '热血乱斗赛,敢来争锋?';
if (battleType === 1 && count === 4) return '2v2对抗赛是兄弟来助我一把!';
if (battleType === 1 && count === 6) return '3v3对抗赛来了马上发车!';
return '星球论箭,来一决高下敢否?';
});
onShareAppMessage(() => {
return {
title: "邀请您进入房间对战",
title: shareTitle.value,
path: "/pages/friend-battle?roomID=" + roomNumber.value,
imageUrl: "",
};
});
/**
* onShow 生命周期:页面显示时刷新房间数据
* 注uni-app 中 onShow 可能早于 onLoad 执行,此时 roomNumber 尚未赋值,
* refreshRoomData 会提前 return。
*/
onShow(() => {
goBattle.value = false;
refreshRoomData();
});
/**
* 页面加载时解析路由参数,初始化房间号
* - 存入本地 ref供页面内部逻辑使用
* - 同步到 Pinia Store供 Header 组件展示房号胶囊)
*/
onLoad(async (options) => {
if (options.roomNumber) {
roomNumber.value = options.roomNumber;
// 立即通知 Header 显示房号,无需等待异步 API 返回
uni.$emit("battle-room-info", { roomNumber: options.roomNumber });
store.updateRoomNumber(options.roomNumber);
}
// 创建者通过 URL 参数 target1→20cm2→40cm初始化靶纸尺寸并持久化到本地缓存
if (options.target) {
targetSize.value = parseInt(options.target) * 20;
uni.setStorageSync(`targetSize_${roomNumber.value}`, targetSize.value);
} else if (roomNumber.value) {
// "返回房间"等无 target 参数的场景:从本地缓存恢复(待 refreshRoomData 进一步覆盖)
const stored = uni.getStorageSync(`targetSize_${roomNumber.value}`);
if (stored) targetSize.value = stored;
}
});
/**
* 组件挂载后:保持屏幕常亮、注册 WebSocket 消息监听
* 房间号已通过 onLoad 同步到 StoreHeader 从 Store 直接读取,无需额外通知
*/
onMounted(() => {
uni.setKeepScreenOn({
keepScreenOn: true,
@@ -285,11 +343,8 @@ onBeforeUnmount(() => {
<GuideTwo>
<view class="battle-guide">
<view class="guide-tips">
<text>弓箭手们人都到齐了吗?</text>
<text v-if="room.battleType === 1">{{
`${room.count / 2}v${room.count / 2}比赛即将开始!`
}}</text>
<text v-if="room.battleType === 2">大乱斗即将开始! </text>
<text class="guide-tips__target">请使用{{ targetSizeLabel }}全环靶</text>
<text class="guide-tips__warn">如果实际靶纸与选择靶纸不同将导致射箭无效</text>
</view>
</view>
</GuideTwo>
@@ -804,4 +859,23 @@ onBeforeUnmount(() => {
border: 1rpx solid #a3793f66;
color: #fed847;
}
.guide-tips__target {
font-weight: 400;
font-size: 26rpx;
color: rgba(255, 217, 71, 0.8);
}
.guide-tips__warn {
font-weight: 400;
font-size: 22rpx;
color: rgba(255, 255, 255, 0.8);
margin-top: 6rpx;
}
.guide-tips {
display: flex;
flex-direction: column;
padding-left: 20rpx;
}
</style>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -79,6 +79,7 @@ export default defineStore("store", {
game: {
roomID: "",
inBattle: false,
roomNumber: "", // 当前房间号,供 Header 展示房号胶囊
},
}),
@@ -135,6 +136,10 @@ export default defineStore("store", {
this.game.roomID = roomID;
this.game.inBattle = inBattle;
},
/** 更新当前房间号,供 Header 组件展示房号胶囊 */
updateRoomNumber(number) {
this.game.roomNumber = number;
},
},
// 开启数据持久化

View File

@@ -14,8 +14,7 @@ function createWebSocket(token, onMessage) {
switch (envVersion) {
case "develop": // 开发版
url = "ws://localhost:8000/socket";
// url = "wss://apitest.shelingxingqiu.com/socket";
url = "wss://apitest.shelingxingqiu.com/socket";
break;
case "trial": // 体验版
url = "wss://apitest.shelingxingqiu.com/socket";