This commit is contained in:
kron
2025-06-24 13:18:03 +08:00
parent fa219892e0
commit c507a40aad
31 changed files with 780 additions and 167 deletions

View File

@@ -18,7 +18,7 @@ const tabs = [
];
function handleTabClick(index) {
if (index !== 0 && !user.value.id) return props.signin();
if (index === 1 && !user.value.id) return props.signin();
if (index === 0) {
uni.navigateTo({
url: "/pages/be-vip",

View File

@@ -52,6 +52,8 @@ const props = defineProps({
:rowCount="arrows.length === 12 ? 6 : 9"
:total="arrows.length"
:scores="arrows.map((a) => a.ring)"
:margin="arrows.length === 12 ? 4 : 1"
:fontSize="arrows.length === 12 ? 25 : 22"
/>
</view>
</template>

View File

@@ -1,6 +1,12 @@
<script setup>
import { ref, watch } from "vue";
import BowPower from "@/components/BowPower.vue";
import { simulShootAPI } from "@/apis";
import useStore from "@/store";
import { storeToRefs } from "pinia";
const store = useStore();
const { device } = storeToRefs(store);
const props = defineProps({
totalRound: {
type: Number,
@@ -38,6 +44,10 @@ const props = defineProps({
type: Boolean,
default: true,
},
start: {
type: Boolean,
default: false,
},
showE: {
type: Boolean,
default: true,
@@ -73,6 +83,9 @@ function calcRealY(num) {
const len = num < 0 ? Math.abs(num) + 20 : 20 - num;
return `calc(${(len / 40) * 100}% - 10px)`;
}
const simulShoot = async () => {
if (device.value.deviceId) await simulShootAPI(device.value.deviceId);
};
</script>
<template>
@@ -90,8 +103,9 @@ function calcRealY(num) {
<view
v-if="scores.length && showRoundTips && showLatestArrow && showE"
class="e-value fade-in"
>经验 +1</view
>
经验 +1
</view>
<view
v-if="scores.length && showRoundTips && showLatestArrow"
class="round-tip fade-in"
@@ -133,6 +147,9 @@ function calcRealY(num) {
<image :src="avatar" mode="widthFix" />
</view>
<text v-if="tips">{{ tips }}</text>
<view class="simul" @click="simulShoot" :style="{ color: '#fff' }">
模拟射箭
</view>
</view>
</template>
@@ -141,9 +158,11 @@ function calcRealY(num) {
width: calc(100% - 30px);
padding: 15px;
/* overflow: hidden; */
position: relative;
}
.target {
position: relative;
padding: 5px;
}
.e-value {
position: absolute;
@@ -166,7 +185,7 @@ function calcRealY(num) {
z-index: 2;
}
.round-tip > text {
font-size: 18px;
font-size: 24px;
margin-left: 5px;
}
.target > image:last-child {
@@ -217,4 +236,11 @@ function calcRealY(num) {
display: block;
margin-top: 20px;
}
.simul {
position: absolute;
bottom: 20px;
right: 20px;
color: #fff;
margin-left: 20px;
}
</style>

View File

@@ -1,14 +1,19 @@
<script setup>
defineProps({
tall: {
type: Boolean,
default: false,
},
noBg: {
type: Boolean,
default: false,
},
type: {
type: Number,
default: 0,
},
});
const bubbleTypes = [
"../static/long-bubble.png",
"../static/long-bubble-middle.png",
"../static/long-bubble-tall.png",
];
</script>
<template>
@@ -17,10 +22,8 @@ defineProps({
<view>
<image
v-if="!noBg"
:src="
tall ? '../static/long-bubble-tall.png' : '../static/long-bubble.png'
"
:style="{ top: tall ? '-6%' : '-12%' }"
:src="bubbleTypes[type]"
:style="{ top: type === 2 ? '-5%' : '-12%' }"
mode="widthFix"
/>
<slot />

View File

@@ -1,10 +1,5 @@
<script setup>
import { ref, onMounted } from "vue";
import useStore from "@/store";
import { simulShootAPI } from "@/apis";
import { storeToRefs } from "pinia";
const store = useStore();
const { device } = storeToRefs(store);
const isIos = ref(true);
const props = defineProps({
@@ -18,12 +13,6 @@ const props = defineProps({
},
});
const simulShoot = async () => {
if (device.value.deviceId) {
await simulShootAPI(device.value.deviceId);
}
};
const onClick = () => {
if (props.onBack) props.onBack();
else uni.navigateBack();
@@ -41,7 +30,6 @@ onMounted(() => {
<image src="../static/back.png" mode="widthFix" />
</view>
<text>{{ title }}</text>
<view class="simul" @click="simulShoot">模拟射箭</view>
</view>
</template>
@@ -67,8 +55,4 @@ onMounted(() => {
.container > text {
color: #fff;
}
.simul {
color: #fff;
margin-left: 20px;
}
</style>

View File

@@ -77,13 +77,14 @@ const onSelect = (userId) => {
<BowTarget
:scores="scores"
:showLatestArrow="false"
:avatar="currentUser.avatar"
:avatar="currentUser ? currentUser.avatar : ''"
/>
</view>
<view class="score-text"
><text :style="{ color: '#fed847' }">12</text>支箭<text
:style="{ color: '#fed847' }"
>100</text
><text :style="{ color: '#fed847' }">{{ scores.length }}</text
>支箭<text :style="{ color: '#fed847' }">{{
scores.reduce((last, next) => last + next.ring, 0)
}}</text
></view
>
<view class="score-row">

View File

@@ -53,16 +53,15 @@ const rowCount = new Array(6).fill(0);
<style scoped>
.container {
width: calc(100% - 75px);
width: calc(100% - 70px);
display: flex;
align-items: center;
border: 1px solid #fff3;
margin: 10px 0;
margin-left: 40px;
margin-left: 35px;
border-radius: 15px;
padding: 10px;
color: #fff9;
margin-right: 20px;
font-size: 14px;
position: relative;
}

View File

@@ -44,7 +44,8 @@ watch(
margin: margin + 'px',
}"
>
{{ scores[index] }}
<image src="../static/score-bg.png" mode="widthFix" />
<text>{{ scores[index] }}</text>
</view>
</view>
</template>
@@ -58,13 +59,22 @@ watch(
margin: 0 5vw;
}
.score-item {
background-image: url("../static/score-bg.png");
/* background-image: url("../static/score-bg.png");
background-size: cover;
background-repeat: no-repeat;
background-position: center;
background-position: center; */
color: #fed847;
display: flex;
justify-content: center;
align-items: center;
position: relative;
}
.score-item > image {
position: absolute;
width: 100%;
top: 5%;
}
.score-item > text {
position: relative;
}
</style>

View File

@@ -52,11 +52,7 @@ setTimeout(() => {
<image src="../static/finish-frame.png" mode="widthFix" />
<text
>完成<text class="gold-text">{{ total }}</text
>获得<text class="gold-text">{{
result.arrows
.map((a) => a.ring)
.reduce((last, next) => last + next, 0)
}}</text
>获得<text class="gold-text">{{ total }}</text
>点经验</text
>
</view>

View File

@@ -118,6 +118,7 @@ onUnmounted(() => {
}
.container > view:first-child > button:last-child > image {
width: 50px;
transform: translateX(10px);
}
.container > view:last-child {
z-index: -1;

View File

@@ -137,7 +137,7 @@ const handleLogin = () => {
align-items: center;
margin-bottom: 20px;
border-bottom: 1px solid #fff3;
padding: 20px 2px;
line-height: 55px;
}
.avatar {
margin: 0;

View File

@@ -22,6 +22,7 @@ const redScores = ref([]);
const blueScores = ref([]);
const tabs = ref(["所有轮次"]);
const players = ref([]);
const allRoundsScore = ref({});
const onClickTab = (index) => {
selected.value = index;
redScores.value = [];
@@ -29,14 +30,22 @@ const onClickTab = (index) => {
const { bluePlayers, redPlayers, roundsData } = props.data;
if (index === 0) {
Object.keys(bluePlayers).forEach((p) => {
allRoundsScore.value[p] = [];
Object.values(roundsData).forEach((round) => {
allRoundsScore.value[p].push(
round[p].reduce((last, next) => last + next.ring, 0)
);
round[p].forEach((arrow) => {
blueScores.value.push(arrow);
});
});
});
Object.keys(redPlayers).forEach((p) => {
allRoundsScore.value[p] = [];
Object.values(roundsData).forEach((round) => {
allRoundsScore.value[p].push(
round[p].reduce((last, next) => last + next.ring, 0)
);
round[p].forEach((arrow) => {
redScores.value.push(arrow);
});
@@ -108,6 +117,15 @@ watch(
:src="player.avatar"
:borderColor="data.bluePlayers[player.playerId] ? 1 : 2"
/>
<view
v-if="selected === 0"
v-for="(ring, index) in allRoundsScore[player.playerId]"
:key="index"
class="score-item"
:style="{ width: '13vw', height: '13vw' }"
>
{{ ring }}
</view>
<view
v-if="selected > 0"
v-for="(score, index) in data.roundsData[selected][player.playerId]"

View File

@@ -10,6 +10,10 @@ const props = defineProps({
type: Boolean,
default: false,
},
onSignin: {
type: Function,
default: () => {},
},
});
const nextLvlPoints = ref("");
const containerWidth = computed(() => (props.showRank ? "72vw" : "100vw"));
@@ -39,46 +43,65 @@ onMounted(() => {
<template>
<view class="container" :style="{ width: containerWidth }">
<Avatar :frame="true" :src="user.avatar" :onClick="toUserPage" :size="42" />
<view class="user-details">
<view class="user-name">
<text>{{ user.nickName }}</text>
<image
class="user-name-image"
src="../static/vip1.png"
mode="widthFix"
/>
</view>
<view class="user-stats">
<text class="level-tag level-tag-first">{{ user.lvlName }}</text>
<text class="level-tag level-tag-second">L{{ user.lvl }}</text>
<view class="rank-tag">
<view
class="rank-tag-progress"
:style="{
width: `${(Math.max(user.scores, 0) / nextLvlPoints) * 100}%`,
}"
<block v-if="user.id"
><Avatar
:frame="true"
:src="user.avatar"
:onClick="toUserPage"
:size="42"
/>
<view class="user-details">
<view class="user-name">
<text>{{ user.nickName }}</text>
<image
class="user-name-image"
src="../static/vip1.png"
mode="widthFix"
/>
<text class="rank-tag-text">
{{ Math.max(user.scores, 0) }}/{{ nextLvlPoints }}
</text>
</view>
<view class="user-stats">
<text class="level-tag level-tag-first">{{ user.lvlName }}</text>
<text class="level-tag level-tag-second">L{{ user.lvl }}</text>
<view class="rank-tag">
<view
class="rank-tag-progress"
:style="{
width: `${(Math.max(user.scores, 0) / nextLvlPoints) * 100}%`,
}"
/>
<text class="rank-tag-text">
{{ Math.max(user.scores, 0) }}/{{ nextLvlPoints }}
</text>
</view>
</view>
</view>
</view>
<view v-if="showRank === true" class="rank-info">
<image
class="rank-info-image"
src="../static/global-rank.png"
mode="widthFix"
/>
<text>本赛季</text>
<text>暂未上榜</text>
<!-- <text class="rank-number"
<view v-if="showRank === true" class="rank-info">
<image
class="rank-info-image"
src="../static/global-rank.png"
mode="widthFix"
/>
<text>本赛季</text>
<text>暂未上榜</text>
<!-- <text class="rank-number"
><text :style="{ color: '#ffd700' }"
>{{ user.points }}/{{ user.rankLvl }}</text
></text
> -->
</view>
</view>
</block>
<block v-else>
<view class="signin">
<image src="../static/user-icon.png" mode="widthFix" />
<view @click="() => (showModal = true)">
<text>新来的弓箭手你好呀~</text>
<view @click="onSignin">
<text>微信登录</text>
<image src="../static/enter-arrow-blue.png" mode="widthFix" />
</view>
</view>
</view>
</block>
</view>
</template>
@@ -163,23 +186,54 @@ onMounted(() => {
}
.rank-info {
width: 68px;
text-align: left;
font-size: 12px;
position: relative;
color: #b3b3b3;
padding-left: 8px;
margin-left: 8px;
display: flex;
flex-direction: column;
}
.rank-info-image {
position: absolute;
top: -6px;
left: -9px;
width: 90px;
}
.rank-info > text {
text-align: center;
}
.rank-number {
display: block;
}
.signin {
display: flex;
align-items: center;
}
.signin > image {
width: 40px;
height: 40px;
}
.signin > view {
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
margin-left: 12px;
font-size: 14px;
}
.signin > view > view:last-child {
display: flex;
align-items: center;
}
.signin > view > view:last-child > text {
color: #39a8ff;
margin-top: 2px;
}
.signin > view > view:last-child > image {
width: 15px;
margin-top: 2px;
}
</style>