Merge branch 'new-race-mode' into test
@@ -9,12 +9,12 @@ defineProps({
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<view class="container">
|
<view class="container">
|
||||||
<image class="shooter2" src="../static/shooter2.png" mode="widthFix" />
|
<image class="shooter2" src="https://static.shelingxingqiu.com/shootmini/static/shooter2.png" mode="widthFix" />
|
||||||
<view class="bg-box">
|
<view class="bg-box">
|
||||||
<image
|
<image
|
||||||
class="bg"
|
class="bg"
|
||||||
v-if="!noBg"
|
v-if="!noBg"
|
||||||
src="../static/long-bubble-border.png"
|
src="https://static.shelingxingqiu.com/shootmini/static/long-bubble-border.png"
|
||||||
mode="widthFix"
|
mode="widthFix"
|
||||||
/>
|
/>
|
||||||
<slot />
|
<slot />
|
||||||
@@ -26,20 +26,21 @@ defineProps({
|
|||||||
.container {
|
.container {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 15px;
|
padding: 0 26rpx 0 28rpx;
|
||||||
margin-bottom: 14rpx;
|
margin-bottom: 14rpx;
|
||||||
width: clac(100% - 30px);
|
width: clac(100% - 54rpx);
|
||||||
}
|
}
|
||||||
.container .shooter2 {
|
.container .shooter2 {
|
||||||
width: 150rpx;
|
display: block;
|
||||||
height: 162rpx;
|
width: 133rpx;
|
||||||
|
height: 144rpx;
|
||||||
}
|
}
|
||||||
.container .bg-box {
|
.container .bg-box {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
position: relative;
|
position: relative;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 55px;
|
height: 128rpx;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ onBeforeUnmount(() => {
|
|||||||
/* 对战房间:整个胶囊作为分享按钮,靠右对齐 */
|
/* 对战房间:整个胶囊作为分享按钮,靠右对齐 */
|
||||||
.battle-room-number {
|
.battle-room-number {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: 10rpx;
|
margin-right: 20rpx;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|||||||
@@ -39,6 +39,9 @@
|
|||||||
{
|
{
|
||||||
"path": "pages/battle-result"
|
"path": "pages/battle-result"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/friend-battle-result"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/point-book-edit"
|
"path": "pages/point-book-edit"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ const checkBowData = () => {
|
|||||||
}deg)`,
|
}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" />
|
<image src="../static/title-mvp.png" mode="widthFix" />
|
||||||
<text
|
<text
|
||||||
>斩获<text
|
>斩获<text
|
||||||
@@ -127,7 +127,7 @@ const checkBowData = () => {
|
|||||||
margin: '0 3px',
|
margin: '0 3px',
|
||||||
fontWeight: '600',
|
fontWeight: '600',
|
||||||
}"
|
}"
|
||||||
>{{ data.mvp[0].totalRings }}</text
|
>{{ data.mvp.totalRings }}</text
|
||||||
>环</text
|
>环</text
|
||||||
>
|
>
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
@@ -42,6 +42,17 @@ const battleTitle = computed(() => {
|
|||||||
return `${half}v${half}对抗赛`;
|
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 ready = ref(false);
|
||||||
const allReady = ref(false);
|
const allReady = ref(false);
|
||||||
const timer = ref(null);
|
const timer = ref(null);
|
||||||
@@ -56,6 +67,15 @@ async function refreshRoomData() {
|
|||||||
const result = await getRoomAPI(roomNumber.value);
|
const result = await getRoomAPI(roomNumber.value);
|
||||||
if (result.started) return;
|
if (result.started) return;
|
||||||
room.value = result;
|
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 = {};
|
owner.value = {};
|
||||||
opponent.value = {};
|
opponent.value = {};
|
||||||
const members = result.members || [];
|
const members = result.members || [];
|
||||||
@@ -241,9 +261,24 @@ const canClick = computed(() => {
|
|||||||
return true;
|
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(() => {
|
onShareAppMessage(() => {
|
||||||
return {
|
return {
|
||||||
title: "邀请您进入房间对战",
|
title: shareTitle.value,
|
||||||
path: "/pages/friend-battle?roomID=" + roomNumber.value,
|
path: "/pages/friend-battle?roomID=" + roomNumber.value,
|
||||||
imageUrl: "",
|
imageUrl: "",
|
||||||
};
|
};
|
||||||
@@ -269,6 +304,15 @@ onLoad(async (options) => {
|
|||||||
roomNumber.value = options.roomNumber;
|
roomNumber.value = options.roomNumber;
|
||||||
store.updateRoomNumber(options.roomNumber);
|
store.updateRoomNumber(options.roomNumber);
|
||||||
}
|
}
|
||||||
|
// 创建者通过 URL 参数 target(1→20cm,2→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;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -299,11 +343,8 @@ onBeforeUnmount(() => {
|
|||||||
<GuideTwo>
|
<GuideTwo>
|
||||||
<view class="battle-guide">
|
<view class="battle-guide">
|
||||||
<view class="guide-tips">
|
<view class="guide-tips">
|
||||||
<text>弓箭手们,人都到齐了吗?</text>
|
<text class="guide-tips__target">请使用{{ targetSizeLabel }}全环靶</text>
|
||||||
<text v-if="room.battleType === 1">{{
|
<text class="guide-tips__warn">如果实际靶纸与选择靶纸不同,将导致射箭无效</text>
|
||||||
`${room.count / 2}v${room.count / 2}比赛即将开始!`
|
|
||||||
}}</text>
|
|
||||||
<text v-if="room.battleType === 2">大乱斗即将开始! </text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</GuideTwo>
|
</GuideTwo>
|
||||||
@@ -818,4 +859,23 @@ onBeforeUnmount(() => {
|
|||||||
border: 1rpx solid #a3793f66;
|
border: 1rpx solid #a3793f66;
|
||||||
color: #fed847;
|
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>
|
</style>
|
||||||
|
|||||||
1063
src/pages/friend-battle-result.vue
Normal file
@@ -20,6 +20,8 @@ const { user } = storeToRefs(store);
|
|||||||
const title = ref("");
|
const title = ref("");
|
||||||
const start = ref(null);
|
const start = ref(null);
|
||||||
const battleId = ref("");
|
const battleId = ref("");
|
||||||
|
/** 对战模式:1=好友约战 2=排位赛,用于结算页跳转判断 */
|
||||||
|
const way = ref(0);
|
||||||
const currentRound = ref(1);
|
const currentRound = ref(1);
|
||||||
const tips = ref("即将开始...");
|
const tips = ref("即将开始...");
|
||||||
const players = ref([]);
|
const players = ref([]);
|
||||||
@@ -28,15 +30,13 @@ const playersScores = ref([]);
|
|||||||
const halfTimeTip = ref(false);
|
const halfTimeTip = ref(false);
|
||||||
const halfRest = ref(false);
|
const halfRest = ref(false);
|
||||||
|
|
||||||
const navigateToResult = () => {
|
|
||||||
uni.redirectTo({ url: `/pages/battle-result?battleId=${battleId.value}` });
|
|
||||||
};
|
|
||||||
|
|
||||||
function recoverData(battleInfo, { force = false } = {}) {
|
function recoverData(battleInfo, { force = false } = {}) {
|
||||||
if (!battleInfo) return;
|
if (!battleInfo) return;
|
||||||
try {
|
try {
|
||||||
if (battleInfo.way === 1) title.value = "好友约战 - 大乱斗";
|
if (battleInfo.way === 1) title.value = "好友约战 - 大乱斗";
|
||||||
if (battleInfo.way === 2) title.value = "排位赛 - 大乱斗";
|
if (battleInfo.way === 2) title.value = "排位赛 - 大乱斗";
|
||||||
|
// 保存 way 供结算跳转时使用
|
||||||
|
way.value = battleInfo.way ?? 0;
|
||||||
|
|
||||||
// 优先使用接口数据,否则使用缓存
|
// 优先使用接口数据,否则使用缓存
|
||||||
if (battleInfo.teams?.[0]?.players) {
|
if (battleInfo.teams?.[0]?.players) {
|
||||||
@@ -122,8 +122,9 @@ async function onReceiveMessage(msg) {
|
|||||||
tips.value = "准备下半场";
|
tips.value = "准备下半场";
|
||||||
} else if (msg.type === MESSAGETYPESV2.BattleEnd) {
|
} else if (msg.type === MESSAGETYPESV2.BattleEnd) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
// 全部跳转到新结算页
|
||||||
uni.redirectTo({
|
uni.redirectTo({
|
||||||
url: "/pages/battle-result?battleId=" + msg.matchId,
|
url: "/pages/friend-battle-result?battleId=" + msg.matchId,
|
||||||
});
|
});
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,10 +38,14 @@ const showRoundTip = ref(false);
|
|||||||
const isFinalShoot = ref(false);
|
const isFinalShoot = ref(false);
|
||||||
const matchStatus = ref(undefined);
|
const matchStatus = ref(undefined);
|
||||||
const updateRemainSecond = ref(0);
|
const updateRemainSecond = ref(0);
|
||||||
|
/** 对战来源类型(1=好友约战,2=匹配对战),用于结算页分流 */
|
||||||
|
const battleWay = ref(0);
|
||||||
|
|
||||||
const recoverData = (battleInfo, {force = false, arrowOnly = false} = {}) => {
|
const recoverData = (battleInfo, {force = false, arrowOnly = false} = {}) => {
|
||||||
try {
|
try {
|
||||||
battleId.value = battleInfo.matchId;
|
battleId.value = battleInfo.matchId;
|
||||||
|
// 存储对战来源,供结算跳转分流使用
|
||||||
|
if (battleInfo.way !== undefined) battleWay.value = battleInfo.way;
|
||||||
|
|
||||||
// 优先使用接口返回的队伍数据,如果没有则尝试从缓存读取(应对匹配刚完成接口未就绪的情况)
|
// 优先使用接口返回的队伍数据,如果没有则尝试从缓存读取(应对匹配刚完成接口未就绪的情况)
|
||||||
const t1 = battleInfo.teams?.[1] || {};
|
const t1 = battleInfo.teams?.[1] || {};
|
||||||
@@ -118,14 +122,16 @@ function onAudioEnded(s) {
|
|||||||
uni.$emit("update-remain", {stop: false, value: updateRemainSecond.value, team: team});
|
uni.$emit("update-remain", {stop: false, value: updateRemainSecond.value, team: team});
|
||||||
}
|
}
|
||||||
if (s.indexOf("比赛结束") >= 0) {
|
if (s.indexOf("比赛结束") >= 0) {
|
||||||
|
console.log("比赛结束");
|
||||||
onBattleEnd()
|
onBattleEnd()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onBattleEnd() {
|
function onBattleEnd() {
|
||||||
if (matchStatus.value === 2) {
|
if (matchStatus.value === 2) {
|
||||||
|
// 全部跳转到新结算页
|
||||||
uni.redirectTo({
|
uni.redirectTo({
|
||||||
url: `/pages/battle-result?battleId=${battleId.value}`,
|
url: `/pages/friend-battle-result?battleId=${battleId.value}`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,12 +208,9 @@ onShow(async () => {
|
|||||||
const result = await getBattleAPI(battleId.value);
|
const result = await getBattleAPI(battleId.value);
|
||||||
if (!result) return;
|
if (!result) return;
|
||||||
if (result.status === 2) {
|
if (result.status === 2) {
|
||||||
uni.showToast({
|
// 比赛已结束(如切后台再回来):跳新结算页
|
||||||
title: "比赛已结束",
|
uni.redirectTo({
|
||||||
icon: "none",
|
url: `/pages/friend-battle-result?battleId=${result.matchId}`,
|
||||||
});
|
|
||||||
uni.navigateBack({
|
|
||||||
delta: 2,
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
recoverData(result, {force: true});
|
recoverData(result, {force: true});
|
||||||
|
|||||||
11
src/static/friend-battle-result/rank-one.svg
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<svg width="156" height="58" viewBox="0 0 156 58" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="编组 5">
|
||||||
|
<rect id="矩形备份" width="156" height="58" fill="url(#paint0_linear_1394_738459)"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_1394_738459" x1="0" y1="87" x2="156" y2="87" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#7E3627"/>
|
||||||
|
<stop offset="1" stop-color="#292826" stop-opacity="0.01"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 540 B |
11
src/static/friend-battle-result/rank-three.svg
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<svg width="156" height="58" viewBox="0 0 156 58" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="编组 12">
|
||||||
|
<rect id="矩形备份" width="156" height="58" fill="url(#paint0_linear_1394_738487)"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_1394_738487" x1="0" y1="87" x2="156" y2="87" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#573E25"/>
|
||||||
|
<stop offset="1" stop-color="#292826" stop-opacity="0.01"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 541 B |
11
src/static/friend-battle-result/rank-two.svg
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<svg width="156" height="58" viewBox="0 0 156 58" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="编组 9">
|
||||||
|
<rect id="矩形备份" width="156" height="58" fill="url(#paint0_linear_1394_738473)"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_1394_738473" x1="0.251953" y1="86.9532" x2="156" y2="86.9532" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#25476F"/>
|
||||||
|
<stop offset="1" stop-color="#292826" stop-opacity="0.01"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 557 B |
|
Before Width: | Height: | Size: 6.2 KiB |
BIN
src/static/mvp-blue.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
src/static/mvp-red.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
src/static/mvp-tip.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 52 KiB |