211 lines
5.8 KiB
Vue
211 lines
5.8 KiB
Vue
<script setup>
|
||
import { computed } from "vue";
|
||
import Container from "@/components/Container.vue";
|
||
import useStore from "@/store";
|
||
import { storeToRefs } from "pinia";
|
||
const store = useStore();
|
||
const { user } = storeToRefs(store);
|
||
|
||
const MAX_LEVEL = 100;
|
||
const LEVEL_NODE_WIDTH_RPX = 72;
|
||
const TRACK_PADDING_RPX = 20;
|
||
const windowWidth = uni.getSystemInfoSync().windowWidth;
|
||
const rpxToPx = (value) => (value * windowWidth) / 750;
|
||
const levels = Array.from({ length: MAX_LEVEL }, (_, index) => index + 1);
|
||
const currentLevel = computed(() => {
|
||
const level = Number(user.value?.lvl) || 1;
|
||
return Math.min(Math.max(level, 1), MAX_LEVEL);
|
||
});
|
||
const currentLevelScrollLeft = computed(() => {
|
||
const nodeWidth = rpxToPx(LEVEL_NODE_WIDTH_RPX);
|
||
const trackPadding = rpxToPx(TRACK_PADDING_RPX);
|
||
const contentWidth = rpxToPx(
|
||
TRACK_PADDING_RPX * 2 + MAX_LEVEL * LEVEL_NODE_WIDTH_RPX
|
||
);
|
||
const currentCenter =
|
||
trackPadding + (currentLevel.value - 1) * nodeWidth + nodeWidth / 2;
|
||
const targetLeft = currentCenter - windowWidth / 2;
|
||
const maxScrollLeft = Math.max(contentWidth - windowWidth, 0);
|
||
|
||
return Math.min(Math.max(targetLeft, 0), maxScrollLeft);
|
||
});
|
||
</script>
|
||
|
||
<template>
|
||
<Container title="等级介绍">
|
||
<view class="container">
|
||
<!-- 等级进度条 -->
|
||
<scroll-view
|
||
class="level-progress"
|
||
scroll-x
|
||
:show-scrollbar="false"
|
||
:scroll-left="currentLevelScrollLeft"
|
||
scroll-with-animation
|
||
>
|
||
<view class="level-track">
|
||
<view
|
||
v-for="level in levels"
|
||
:id="`level-${level}`"
|
||
:key="level"
|
||
:class="[
|
||
'level-node',
|
||
level < currentLevel ? 'level-node--done' : '',
|
||
level === currentLevel ? 'level-node--current' : '',
|
||
]"
|
||
>
|
||
<view class="level-node__top">
|
||
<view class="level-node__dot" />
|
||
<view v-if="level < MAX_LEVEL" class="level-node__line" />
|
||
</view>
|
||
<text class="level-node__label">{{ level }}</text>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
|
||
<!-- 说明文本 -->
|
||
<view class="body">
|
||
<view class="intro-text">
|
||
在射灵世界中,等级是衡量您射箭技能的重要指标,而经验则是您提升等级的关键。具体的要求如下:
|
||
</view>
|
||
|
||
<view class="section">
|
||
<view class="title">一、经验的获取规则</view>
|
||
<view class="text">
|
||
每射出一支箭,无论是否中靶、环数高低,您将获得1点经验。这是您提升射灵等级的基本方式,每一次射箭都是您向更高目标迈进的一步。
|
||
</view>
|
||
</view>
|
||
|
||
<view class="section">
|
||
<view class="title">二、解锁特权与玩法</view>
|
||
<view class="text">
|
||
当您等级达到9级时,将解锁“约战模式”。在这个模式中,您可以邀请您的好友进行切磋,与他们展开一场精彩的射箭对决。通过与好友的对抗,您不仅可以收获友谊和欢乐,还能在交流中学习到更多的技巧和经验。
|
||
</view>
|
||
<view class="text">
|
||
当您等级达到16级时,将解锁“对战模式”,每次对战都是一次难得的学习机会。您可以借此机会提升自己的水平,同时也为您的好友提供帮助和建议。此外,约战模式还为您提供了展示自己技艺的平台,让您在与好友的互动中感受到射箭的乐趣和成就感。
|
||
</view>
|
||
<view class="text">
|
||
未来我们将推出“押豆模式”,敬请期待!当您等级达到22级时,您可以与相同段位的玩家进行对抗,赢家将收获所有的灵豆。这不仅增加了游戏的趣味性和挑战性,还为您提供了赢取更多灵豆的机会。通过与更多玩家的对战,您可以不断提升自己的技术水平。
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</Container>
|
||
</template>
|
||
|
||
<style scoped>
|
||
.container {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
|
||
.level-progress {
|
||
width: 100%;
|
||
white-space: nowrap;
|
||
padding: 24rpx 0 34rpx;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.level-track {
|
||
display: inline-flex;
|
||
align-items: flex-start;
|
||
padding-left: 20rpx;
|
||
padding-right: 20rpx;
|
||
}
|
||
|
||
.level-node {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
width: 72rpx;
|
||
flex: 0 0 72rpx;
|
||
}
|
||
|
||
.level-node__top {
|
||
display: flex;
|
||
align-items: center;
|
||
width: 100%;
|
||
}
|
||
|
||
.level-node__dot {
|
||
width: 28rpx;
|
||
height: 28rpx;
|
||
border-radius: 50%;
|
||
border: 3rpx solid rgba(255, 255, 255, 0.45);
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.level-node__line {
|
||
flex: 1;
|
||
height: 2rpx;
|
||
background-color: rgba(255, 255, 255, 0.45);
|
||
}
|
||
|
||
.level-node__label {
|
||
width: 28rpx;
|
||
margin-top: 14rpx;
|
||
color: rgba(255, 255, 255, 0.45);
|
||
font-size: 24rpx;
|
||
line-height: 28rpx;
|
||
text-align: center;
|
||
}
|
||
|
||
.level-node--done .level-node__dot {
|
||
background-color: #ffffff;
|
||
border-color: #ffffff;
|
||
}
|
||
|
||
.level-node--done .level-node__line {
|
||
background-color: rgba(255, 255, 255, 0.8);
|
||
}
|
||
|
||
.level-node--done .level-node__label {
|
||
color: rgba(255, 255, 255, 0.72);
|
||
}
|
||
|
||
.level-node--current .level-node__dot {
|
||
background-color: #fed847;
|
||
border-color: #fed847;
|
||
}
|
||
|
||
.level-node--current .level-node__line {
|
||
background-color: rgba(255, 255, 255, 0.45);
|
||
}
|
||
|
||
.level-node--current .level-node__label {
|
||
color: #fed847;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.body {
|
||
height: calc(100% - 146rpx);
|
||
background-color: #ffffff;
|
||
padding: 30rpx;
|
||
}
|
||
|
||
.intro-text {
|
||
font-size: 14px;
|
||
color: #333333;
|
||
line-height: 1.6;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.section {
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.title {
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
color: #333333;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.text {
|
||
font-size: 14px;
|
||
color: #666666;
|
||
line-height: 1.6;
|
||
margin-bottom: 10px;
|
||
text-align: justify;
|
||
}
|
||
</style>
|