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;
@@ -51,7 +59,16 @@ defineProps({
}"
>
- {{ player.name }}
+
+ {{ player.name }}
+
+ {{ player.name }}
+
+
+ {{ player.name }}
- {{ player.name }}
+
+ {{ player.name }}
+
+ {{ player.name }}
+
+
+ {{ player.name }}
- {{ player.name }}
+
+ {{ player.name }}
+
+ {{ player.name }}
+
+
+ {{ player.name }}
@@ -183,6 +218,13 @@ defineProps({
text-overflow: ellipsis;
text-align: center;
}
+view.player-name {
+ justify-content: center;
+}
+.player-name .member-nickname__text,
+.player-name .member-nickname__shine {
+ font-size: 12px;
+}
.left-winner-badge {
position: absolute;
width: 50px;
diff --git a/src/components/BowData.vue b/src/components/BowData.vue
index 7854645..409f98f 100644
--- a/src/components/BowData.vue
+++ b/src/components/BowData.vue
@@ -1,4 +1,5 @@
@@ -31,7 +39,16 @@ const rowCount = new Array(6).fill(0);
mode="widthFix"
/>
- {{ player.name }}
+
+ {{ player.name }}
+
+ {{ player.name }}
+
+
+ {{ player.name }}
@@ -96,6 +113,13 @@ const rowCount = new Array(6).fill(0);
text-overflow: ellipsis;
width: 20%;
}
+.player-score-name {
+ width: 20%;
+}
+.player-score-name .member-nickname__text,
+.player-score-name .member-nickname__shine {
+ font-size: 14px;
+}
.container > view:nth-child(4) {
display: flex;
flex-direction: column;
diff --git a/src/components/PointRankItem.vue b/src/components/PointRankItem.vue
index 863b024..7d52145 100644
--- a/src/components/PointRankItem.vue
+++ b/src/components/PointRankItem.vue
@@ -22,6 +22,15 @@ const props = defineProps({
const like = ref(props.data.ifLike);
const likeCount = ref(props.data.likeTotal || 0);
+const isMember = (data = {}) => data.vip === true || data.sVip === true;
+
+const getMemberNicknameClass = (data = {}) => [
+ "point-rank-name",
+ "member-nickname",
+ data.vip === true && data.sVip !== true ? "member-nickname--vip" : "",
+ data.sVip === true ? "member-nickname--svip" : "",
+];
+
watch(
() => props.data,
(newVal) => {
@@ -53,7 +62,13 @@ const onClick = async () => {
- {{ data.name }}
+
+ {{ data.name }}
+
+ {{ data.name }}
+
+
+ {{ data.name }}
{{ data.totalDay }}天
@@ -118,6 +133,14 @@ const onClick = async () => {
color: #333333;
margin-bottom: 5rpx;
}
+.rank-item > view:nth-child(2) > view:last-child > .point-rank-name {
+ width: 200rpx;
+ margin-bottom: 5rpx;
+}
+.point-rank-name .member-nickname__text,
+.point-rank-name .member-nickname__shine {
+ font-size: 28rpx;
+}
.rank-item > view:nth-child(2) > view:last-child > view {
display: flex;
align-items: center;
diff --git a/src/components/UserHeader.vue b/src/components/UserHeader.vue
index 6e1ba51..5b375fe 100644
--- a/src/components/UserHeader.vue
+++ b/src/components/UserHeader.vue
@@ -19,6 +19,8 @@ const nextLvlPoints = ref(0);
const containerWidth = computed(() =>
props.showRank ? "72%" : "calc(100% - 15px)"
);
+const isSVip = computed(() => user.value.sVip === true);
+const isVip = computed(() => user.value.vip === true && !isSVip.value);
const toUserPage = () => {
// 获取当前页面路径
const pages = getCurrentPages();
@@ -69,7 +71,18 @@ watch(
/>
- {{ user.nickName }}
+
+ {{ user.nickName }}
+ {{
+ user.nickName
+ }}
+
text:first-child {
- font-size: 13px;
+.user-name .member-nickname {
max-width: 180rpx;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
+}
+
+.user-name .member-nickname__text,
+.user-name .member-nickname__shine {
+ font-size: 13px;
}
.user-name-image {
diff --git a/src/pages.json b/src/pages.json
index 1b3e684..31de134 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -114,9 +114,9 @@
{
"path": "pages/match-detail"
},
- {
- "path": "pages/team-bow-data"
- },
+ {
+ "path": "pages/team-battle/team-bow-data"
+ },
{
"path": "pages/melee-bow-data"
},
diff --git a/src/pages/friend-battle-result.vue b/src/pages/friend-battle-result.vue
index f231ce2..d290a7f 100644
--- a/src/pages/friend-battle-result.vue
+++ b/src/pages/friend-battle-result.vue
@@ -92,6 +92,14 @@ const mvpTeam = computed(() => {
return blueTeamPlayers.value.some((p) => p.id === mvpPlayer.value.id) ? 1 : 2;
});
+const isMember = (player = {}) => player.vip === true || player.sVip === true;
+
+const getMemberNicknameClass = (player = {}) => [
+ "member-nickname",
+ player.vip === true && player.sVip !== true ? "member-nickname--vip" : "",
+ player.sVip === true ? "member-nickname--svip" : "",
+];
+
/**
* 激励语图片 URL(在 onLoad 中确定 ifWin 后赋值,避免 Math.random 放在 computed 里产生缓存不一致问题)
*/
@@ -128,6 +136,8 @@ const meleeRankList = computed(() => {
id: p.id,
avatar: p.avatar || "",
name: p.name || "",
+ vip: p.vip,
+ sVip: p.sVip,
// rank_lvl 字段可能缺失,缺失时显示空字符串,避免 getLvlName(undefined) 返回错误段位名
lvlName: p.rank_lvl != null ? getLvlName(p.rank_lvl) : "",
totalRing: resultItem.totalRing ?? 0,
@@ -332,7 +342,20 @@ function goBack() {
- {{ p.name }}
+
+ {{ p.name }}
+
+ {{ p.name }}
+
+
+ {{ p.name }}
@@ -340,7 +363,20 @@ function goBack() {
- {{ p.name }}
+
+ {{ p.name }}
+
+ {{ p.name }}
+
+
+ {{ p.name }}
@@ -385,7 +421,16 @@ function goBack() {
:size="53"
:borderColor="mvpTeam === 1 ? '#5FADFF' : '#FF6060'"
/>
- {{ mvpPlayer.name }}
+
+ {{ mvpPlayer.name }}
+
+ {{ mvpPlayer.name }}
+
+
+ {{ mvpPlayer.name }}
@@ -433,7 +478,16 @@ function goBack() {
- {{ item.name }}
+
+ {{ item.name }}
+
+ {{ item.name }}
+
+
+ {{ item.name }}
{{ item.lvlName }}
@@ -613,6 +667,12 @@ function goBack() {
white-space: nowrap;
}
+.player-name .member-nickname__text,
+.player-name .member-nickname__shine {
+ font-size: 22rpx;
+ font-weight: 400;
+}
+
/* ---- 得分行 ---- */
.vs-scores-row {
position: relative;
@@ -752,6 +812,11 @@ function goBack() {
white-space: nowrap;
}
+.mvp-name .member-nickname__text,
+.mvp-name .member-nickname__shine {
+ font-size: 24rpx;
+}
+
/* ============================
查看完整成绩链接
============================ */
@@ -1072,6 +1137,12 @@ function goBack() {
white-space: nowrap;
}
+.rank-player-name .member-nickname__text,
+.rank-player-name .member-nickname__shine {
+ font-size: 28rpx;
+ font-weight: 500;
+}
+
.rank-player-lvl {
font-size: 22rpx;
color: rgba(255, 255, 255, 0.5);
diff --git a/src/pages/friend-battle.vue b/src/pages/friend-battle.vue
index 2cbdda1..157c17e 100644
--- a/src/pages/friend-battle.vue
+++ b/src/pages/friend-battle.vue
@@ -1,5 +1,5 @@
@@ -34,7 +36,7 @@ onLoad(async (options) => {
-->
-
+
{{ arrows.length }}
diff --git a/src/pages/my-device.vue b/src/pages/my-device.vue
index ad58d3c..9de1b90 100644
--- a/src/pages/my-device.vue
+++ b/src/pages/my-device.vue
@@ -1,5 +1,5 @@
@@ -51,7 +59,16 @@ defineProps({
}"
>
- {{ player.name }}
+
+ {{ player.name }}
+
+ {{ player.name }}
+
+
+ {{ player.name }}
- {{ player.name }}
+
+ {{ player.name }}
+
+ {{ player.name }}
+
+
+ {{ player.name }}
- {{ player.name }}
+
+ {{ player.name }}
+
+ {{ player.name }}
+
+
+ {{ player.name }}
@@ -183,6 +218,13 @@ defineProps({
text-overflow: ellipsis;
text-align: center;
}
+view.player-name {
+ justify-content: center;
+}
+.player-name .member-nickname__text,
+.player-name .member-nickname__shine {
+ font-size: 12px;
+}
.left-winner-badge {
position: absolute;
width: 50px;
diff --git a/src/pages/team-battle/components/BowTarget.vue b/src/pages/team-battle/components/BowTarget.vue
index 9af060a..c303250 100644
--- a/src/pages/team-battle/components/BowTarget.vue
+++ b/src/pages/team-battle/components/BowTarget.vue
@@ -35,6 +35,14 @@ const props = defineProps({
type: Array,
default: () => [],
},
+ redTeam: {
+ type: Array,
+ default: () => [],
+ },
+ blueTeam: {
+ type: Array,
+ default: () => [],
+ },
latestShotFlash: {
type: Object,
default: null,
@@ -92,8 +100,17 @@ function buildShotEffectKey(team, shot, fallbackKey = "") {
);
}
-function shouldPlayShotEffect(shot) {
- return !!shot && Number(shot.ring) > 0;
+function findShotPlayer(shot, team) {
+ const players = team === "red" ? props.redTeam : props.blueTeam;
+ return players.find((player) => String(player?.id) === String(shot?.playerId));
+}
+
+function isSvipShot(shot, team) {
+ return findShotPlayer(shot, team)?.sVip === true;
+}
+
+function shouldPlayShotEffect(shot, team) {
+ return !!shot && Number(shot.ring) > 0 && isSvipShot(shot, team);
}
function clearTipTimer() {
@@ -204,7 +221,7 @@ function showShotFlash(flash) {
}
const team = flash.team === "red" ? "red" : "blue";
- if (shouldPlayShotEffect(shootData)) {
+ if (shouldPlayShotEffect(shootData, team)) {
triggerShotEffect(team, shootData, flash.key);
return;
}
@@ -310,6 +327,15 @@ function getHitStyle(shot) {
};
}
+function getSvipHitBgStyle(shot) {
+ const radius = currentHitRadiusPx.value;
+ const point = getShotPoint(shot);
+
+ return {
+ ...getTargetPositionStyle(point, radius),
+ };
+}
+
function getRoundTipStyle(shot) {
const point = getShotPoint(shot, true);
return getTargetPositionStyle(
@@ -445,6 +471,18 @@ onBeforeUnmount(() => {
}}环
+
+
@@ -30,6 +31,18 @@ const getPos = (id) => {
return sort * 40;
};
+const getMemberNicknameClass = () => [
+ "current-shooter-name",
+ "member-nickname",
+ currentPlayer.value?.vip === true && currentPlayer.value?.sVip !== true
+ ? "member-nickname--vip"
+ : "",
+ currentPlayer.value?.sVip === true ? "member-nickname--svip" : "",
+];
+
+const isCurrentPlayerMember = () =>
+ currentPlayer.value?.vip === true || currentPlayer.value?.sVip === true;
+
const syncPlayers = () => {
const nextPlayers = {};
const shooterId = props.currentShooterId;
@@ -40,12 +53,14 @@ const syncPlayers = () => {
currentTeam.value = !!shooterId && shooterIndex >= 0;
firstName.value = "";
+ currentPlayer.value = null;
if (currentTeam.value) {
const target = nextTeam.splice(shooterIndex, 1)[0];
if (target) {
nextTeam.unshift(target);
firstName.value = target.name || "";
+ currentPlayer.value = target;
}
}
@@ -93,8 +108,20 @@ watch(
>{{ isRed ? "红队" : "蓝队" }}
+
+ {{ firstName }}
+
+ {{ firstName }}
+
+
+import { ref } from "vue";
+import { onLoad } from "@dcloudio/uni-app";
+import Container from "./components/Container.vue";
+import BowTarget from "./components/BowTarget.vue";
+import Avatar from "./components/Avatar.vue";
+import { roundsName } from "@/constants";
+import { getBattleAPI } from "@/apis";
+const selected = ref(0);
+const redScores = ref([]);
+const blueScores = ref([]);
+const redTeam = ref([]);
+const blueTeam = ref([]);
+const tabs = ref([]);
+const players = ref([]);
+const data = ref({});
+
+const loadArrows = (round) => {
+ round.shoots[1].forEach((arrow) => {
+ blueScores.value.push(arrow);
+ });
+ round.shoots[2].forEach((arrow) => {
+ redScores.value.push(arrow);
+ });
+};
+onLoad(async (options) => {
+ if (!options.battleId) return;
+ const result = await getBattleAPI(options.battleId || "57943107462893568");
+ data.value = result;
+ blueTeam.value = data.value.teams?.[1]?.players || [];
+ redTeam.value = data.value.teams?.[2]?.players || [];
+ blueTeam.value.forEach((p, index) => {
+ players.value.push(p);
+ players.value.push(redTeam.value[index]);
+ });
+ Object.values(data.value.rounds).forEach((round, index) => {
+ if (round.ifGold) tabs.value.push(`决金箭`);
+ else tabs.value.push(`第${roundsName[index + 1]}轮`);
+ });
+ selected.value = Number(options.selected || 0);
+ onClickTab(selected.value);
+});
+const onClickTab = (index) => {
+ selected.value = index;
+ redScores.value = [];
+ blueScores.value = [];
+ loadArrows(data.value.rounds[index]);
+};
+
+
+
+
+
+
+ onClickTab(index)"
+ :class="selected === index ? 'selected-tab' : ''"
+ >
+ {{ tab }}
+
+
+
+
+
+
+
+
+
+
+ {{ score.ringX ? "X" : score.ring }}
+
+
+
+
+
+
+
+
+
diff --git a/src/static/vip/svip-jian.png b/src/static/vip/svip-jian.png
index 1d3588d..f4fb264 100644
Binary files a/src/static/vip/svip-jian.png and b/src/static/vip/svip-jian.png differ
diff --git a/src/static/vip/svip-lie.png b/src/static/vip/svip-lie.png
index a610d4c..8fb9577 100644
Binary files a/src/static/vip/svip-lie.png and b/src/static/vip/svip-lie.png differ
diff --git a/src/static/vip/svip-title.png b/src/static/vip/svip-title.png
deleted file mode 100644
index d360349..0000000
Binary files a/src/static/vip/svip-title.png and /dev/null differ
diff --git a/src/static/vip/svip-title2.png b/src/static/vip/svip-title2.png
deleted file mode 100644
index ca17c17..0000000
Binary files a/src/static/vip/svip-title2.png and /dev/null differ
diff --git a/src/static/vip/svip-xuan.png b/src/static/vip/svip-xuan.png
new file mode 100644
index 0000000..48d9b2c
Binary files /dev/null and b/src/static/vip/svip-xuan.png differ
diff --git a/src/static/vip/vip-bg.png b/src/static/vip/vip-bg.png
deleted file mode 100644
index 952845e..0000000
Binary files a/src/static/vip/vip-bg.png and /dev/null differ
diff --git a/src/static/vip/vip-title.png b/src/static/vip/vip-title.png
deleted file mode 100644
index 1fbc913..0000000
Binary files a/src/static/vip/vip-title.png and /dev/null differ
diff --git a/src/static/vip/vip-title2.png b/src/static/vip/vip-title2.png
deleted file mode 100644
index 3656d63..0000000
Binary files a/src/static/vip/vip-title2.png and /dev/null differ