UI更新
@@ -13,7 +13,7 @@ const props = defineProps({
|
||||
|
||||
const tabs = [
|
||||
{ image: "../static/tab-vip.png" },
|
||||
{ image: "../static/tab-grow.png" },
|
||||
{ image: "../static/tab-point-book.png" },
|
||||
{ image: "../static/tab-mall.png" },
|
||||
];
|
||||
|
||||
@@ -26,7 +26,7 @@ function handleTabClick(index) {
|
||||
}
|
||||
if (index === 1) {
|
||||
uni.navigateTo({
|
||||
url: "/pages/my-growth",
|
||||
url: "/pages/point-book-create",
|
||||
});
|
||||
}
|
||||
if (index === 2) {
|
||||
@@ -45,14 +45,11 @@ function handleTabClick(index) {
|
||||
:key="index"
|
||||
class="tab-item"
|
||||
@click="handleTabClick(index)"
|
||||
>
|
||||
<image
|
||||
:src="tab.image"
|
||||
:style="{
|
||||
width: index === 1 ? '100px' : '40px',
|
||||
width: index === 1 ? '32%' : '10%',
|
||||
}"
|
||||
mode="widthFix"
|
||||
/>
|
||||
>
|
||||
<image :src="tab.image" mode="widthFix" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@@ -76,10 +73,16 @@ function handleTabClick(index) {
|
||||
.tab-item {
|
||||
z-index: 1;
|
||||
}
|
||||
.tab-item > image {
|
||||
width: 88%;
|
||||
}
|
||||
.tab-item:nth-child(2) {
|
||||
transform: translateY(10px);
|
||||
transform: translateY(20%) translateX(25%);
|
||||
}
|
||||
.tab-item:nth-child(3) {
|
||||
transform: translateY(-10%) translateX(5%);
|
||||
}
|
||||
.tab-item:nth-child(4) {
|
||||
transform: translateY(10px) translateX(-10px);
|
||||
transform: translateY(20%) translateX(-25%);
|
||||
}
|
||||
</style>
|
||||
|
||||
17
src/components/BowTargetEdit.vue
Normal file
@@ -0,0 +1,17 @@
|
||||
<script setup></script>
|
||||
|
||||
<template>
|
||||
<view class="container">
|
||||
<image src="../static/bow-target.png" mode="widthFix" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
width: 90%;
|
||||
margin: 10px auto;
|
||||
}
|
||||
.container > image {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted } from "vue";
|
||||
import { ref, watch, onMounted, onUnmounted } from "vue";
|
||||
const props = defineProps({
|
||||
itemIndex: {
|
||||
type: Number,
|
||||
@@ -21,6 +21,10 @@ const props = defineProps({
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
});
|
||||
const bowTypes = [
|
||||
{
|
||||
@@ -96,6 +100,36 @@ const onMeterChange = (e) => {
|
||||
meter.value = e.detail.value;
|
||||
props.onSelect(props.itemIndex, e.detail.value);
|
||||
};
|
||||
watch(
|
||||
() => props.value,
|
||||
(newValue) => {
|
||||
if (!newValue) return;
|
||||
if (props.itemIndex === 0) {
|
||||
bowTypes.forEach((item, index) => {
|
||||
if (item.name === newValue) {
|
||||
selectedIndex.value = index;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (props.itemIndex === 1) {
|
||||
distances.forEach((item, index) => {
|
||||
if (item == newValue) {
|
||||
selectedIndex.value = index;
|
||||
}
|
||||
if (selectedIndex.value === -1) {
|
||||
meter.value = newValue;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (props.itemIndex === 2) {
|
||||
bowtargetTypes.forEach((item, index) => {
|
||||
if (item === newValue) {
|
||||
selectedIndex.value = index;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -112,21 +146,13 @@ const onMeterChange = (e) => {
|
||||
}}</text>
|
||||
<block>
|
||||
<text :style="{ opacity: expand ? 0 : 1 }" v-if="itemIndex === 0">{{
|
||||
bowTypes[selectedIndex]
|
||||
? bowTypes[selectedIndex].name
|
||||
: itemTexts[itemIndex]
|
||||
value || itemTexts[itemIndex]
|
||||
}}</text>
|
||||
<text :style="{ opacity: expand ? 0 : 1 }" v-if="itemIndex === 1">{{
|
||||
distances[selectedIndex]
|
||||
? distances[selectedIndex] + " 米"
|
||||
: selectedIndex === 9
|
||||
? meter + " 米"
|
||||
: itemTexts[itemIndex]
|
||||
value ? value + "米" : itemTexts[itemIndex]
|
||||
}}</text>
|
||||
<text :style="{ opacity: expand ? 0 : 1 }" v-if="itemIndex === 2">{{
|
||||
bowtargetTypes[selectedIndex]
|
||||
? bowtargetTypes[selectedIndex]
|
||||
: itemTexts[itemIndex]
|
||||
value || itemTexts[itemIndex]
|
||||
}}</text>
|
||||
<text :style="{ opacity: expand ? 0 : 1 }" v-if="itemIndex === 3">{{
|
||||
selectedIndex !== -1 && secondSelectIndex !== -1
|
||||
@@ -174,6 +200,7 @@ const onMeterChange = (e) => {
|
||||
}"
|
||||
>
|
||||
<input
|
||||
v-model="meter"
|
||||
placeholder="自定义"
|
||||
placeholder-style="color: #DDDDDD"
|
||||
@focus="() => (selectedIndex = 9)"
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"pages": [
|
||||
{
|
||||
"path": "pages/point-book-create"
|
||||
"path": "pages/index"
|
||||
},
|
||||
{
|
||||
"path": "pages/point-book-edit"
|
||||
},
|
||||
{
|
||||
"path": "pages/index"
|
||||
"path": "pages/point-book-create"
|
||||
},
|
||||
{
|
||||
"path": "pages/point-book-list"
|
||||
|
||||
@@ -18,7 +18,8 @@ import { topThreeColors } from "@/constants";
|
||||
import useStore from "@/store";
|
||||
import { storeToRefs } from "pinia";
|
||||
const store = useStore();
|
||||
const { updateConfig, updateUser, updateDevice, updateRank } = store;
|
||||
const { updateConfig, updateUser, updateDevice, updateRank, getLvlName } =
|
||||
store;
|
||||
// 使用storeToRefs,用于UI里显示,保持响应性
|
||||
const { user, device, rankData } = storeToRefs(store);
|
||||
const showModal = ref(false);
|
||||
@@ -109,11 +110,10 @@ const comingSoon = () => {
|
||||
<view class="feature-grid">
|
||||
<view class="bow-card">
|
||||
<image
|
||||
src="https://api.shelingxingqiu.com/attachment/2025-07-15/dbciq9qhkpd3pqxawo.webp"
|
||||
src="../static/my-bow.png"
|
||||
mode="widthFix"
|
||||
@click="() => toPage('/pages/my-device')"
|
||||
/>
|
||||
|
||||
<text v-if="!user.id">我的弓箭</text>
|
||||
<text v-if="user.id && !device.deviceId">请绑定设备</text>
|
||||
<text
|
||||
@@ -123,7 +123,7 @@ const comingSoon = () => {
|
||||
>{{ device.deviceName }}</text
|
||||
>
|
||||
<image
|
||||
src="../static/a2@2x.png"
|
||||
src="../static/first-try.png"
|
||||
mode="widthFix"
|
||||
@click="() => toPage('/pages/first-try')"
|
||||
/>
|
||||
@@ -135,20 +135,17 @@ const comingSoon = () => {
|
||||
<text>快来报到吧~</text>
|
||||
</BubbleTip>
|
||||
</view>
|
||||
|
||||
<view class="practice-card" @click="() => toPage('/pages/practise')">
|
||||
<image src="../static/a2@2x(1).png" mode="widthFix" />
|
||||
<view class="play-card">
|
||||
<view @click="() => toPage('/pages/practise')">
|
||||
<image src="../static/my-practise.png" mode="widthFix" />
|
||||
</view>
|
||||
<view @click="() => toPage('/pages/friend-battle')">
|
||||
<image src="../static/friend-battle.png" mode="widthFix" />
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="friend-card"
|
||||
@click="() => toPage('/pages/friend-battle')"
|
||||
>
|
||||
<image src="../static/a3@2x.png" mode="widthFix" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="ranking-section">
|
||||
<image src="../static/a4@2x.png" mode="widthFix" />
|
||||
<image src="../static/rank-bg.png" mode="widthFix" />
|
||||
<button
|
||||
class="into-btn"
|
||||
@click="() => toPage('/pages/ranking')"
|
||||
@@ -185,7 +182,30 @@ const comingSoon = () => {
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="region-stats">
|
||||
<view class="my-data">
|
||||
<view @click="() => toPage('/pages/my-growth')">
|
||||
<image src="../static/my-growth.png" mode="widthFix" />
|
||||
</view>
|
||||
<view>
|
||||
<view>
|
||||
<text>段位</text>
|
||||
<text>{{ user.scores ? getLvlName(user.scores) : "-" }}</text>
|
||||
</view>
|
||||
<view>
|
||||
<text>赛季平均环数</text>
|
||||
<text>{{ user.avg_ring ? user.avg_ring + "环" : "-" }}</text>
|
||||
</view>
|
||||
<view>
|
||||
<text>赛季胜率</text>
|
||||
<text>{{
|
||||
user.avg_win
|
||||
? Number((user.avg_win * 100).toFixed(2)) + "%"
|
||||
: "-"
|
||||
}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- <view class="region-stats">
|
||||
<view
|
||||
v-for="(region, index) in [
|
||||
{ name: '广东', score: 4291 },
|
||||
@@ -237,7 +257,7 @@ const comingSoon = () => {
|
||||
<text>...</text>
|
||||
<text>更多</text>
|
||||
</view>
|
||||
</view>
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
<SModal :show="showModal" :onClose="() => (showModal = false)">
|
||||
@@ -254,17 +274,19 @@ const comingSoon = () => {
|
||||
}
|
||||
|
||||
.feature-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-template-areas: "bow practice" "bow friend";
|
||||
row-gap: 5px;
|
||||
column-gap: 10px;
|
||||
margin-bottom: 10px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.feature-grid > view {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.bow-card {
|
||||
grid-area: bow;
|
||||
position: relative;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.feature-grid > view > image {
|
||||
@@ -281,21 +303,16 @@ const comingSoon = () => {
|
||||
color: #b3b3b3;
|
||||
}
|
||||
|
||||
.bow-card > image:first-child {
|
||||
transform: scaleY(1.08) translateY(9px);
|
||||
}
|
||||
|
||||
.bow-card > image:nth-child(3) {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.practice-card {
|
||||
grid-area: practice;
|
||||
width: 100%;
|
||||
.play-card {
|
||||
width: 48%;
|
||||
margin-left: 2%;
|
||||
}
|
||||
|
||||
.friend-card {
|
||||
grid-area: friend;
|
||||
.play-card > view > image {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -382,7 +399,7 @@ const comingSoon = () => {
|
||||
}
|
||||
|
||||
.more-players {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
background: #3C445A;
|
||||
font-size: 9px;
|
||||
line-height: 80rpx;
|
||||
text-align: center;
|
||||
@@ -447,4 +464,39 @@ const comingSoon = () => {
|
||||
line-height: 20px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.my-data {
|
||||
display: flex;
|
||||
margin-top: 20px;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.my-data > view:first-child {
|
||||
width: 28%;
|
||||
}
|
||||
.my-data > view:first-child > image {
|
||||
width: 100%;
|
||||
transform: translateX(-8px);
|
||||
}
|
||||
.my-data > view:nth-child(2) {
|
||||
width: 68%;
|
||||
font-size: 12px;
|
||||
color: #fff6;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.my-data > view:nth-child(2) > view:nth-child(2) {
|
||||
width: 38%;
|
||||
}
|
||||
.my-data > view:nth-child(2) > view {
|
||||
width: 28%;
|
||||
border-radius: 10px;
|
||||
background: linear-gradient(180deg, #303b4c 30%, #2c384a 100%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.my-data > view:nth-child(2) > view > text:last-child {
|
||||
color: #fff;
|
||||
line-height: 25px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -24,6 +24,7 @@ const onSelect = (itemIndex, value) => {
|
||||
else if (itemIndex === 1) distance.value = value;
|
||||
else if (itemIndex === 2) bowtargetType.value = value;
|
||||
else if (itemIndex === 3) amountGroup.value = value;
|
||||
if (itemIndex < 3) expandIndex.value += 1;
|
||||
if (
|
||||
bowType.value &&
|
||||
distance.value &&
|
||||
@@ -44,6 +45,14 @@ const toEditPage = () => {
|
||||
url: "/pages/point-book-edit",
|
||||
});
|
||||
};
|
||||
onMounted(() => {
|
||||
const pointBook = uni.getStorageSync("point-book");
|
||||
if (pointBook) {
|
||||
bowType.value = pointBook.bowType;
|
||||
distance.value = pointBook.distance;
|
||||
bowtargetType.value = pointBook.bowtargetType;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -54,25 +63,31 @@ const toEditPage = () => {
|
||||
title="计分本"
|
||||
>
|
||||
<view class="container">
|
||||
<image src="../static/point-book-banner.png" mode="widthFix" />
|
||||
<image
|
||||
src="https://api.shelingxingqiu.com/attachment/2025-07-30/dbp9r4762kiaqykbpn.png"
|
||||
mode="widthFix"
|
||||
/>
|
||||
<view>
|
||||
<EditOption
|
||||
:itemIndex="0"
|
||||
:expand="expandIndex === 0"
|
||||
:onExpand="onExpandChange"
|
||||
:onSelect="onSelect"
|
||||
:value="bowType"
|
||||
/>
|
||||
<EditOption
|
||||
:itemIndex="1"
|
||||
:expand="expandIndex === 1"
|
||||
:onExpand="onExpandChange"
|
||||
:onSelect="onSelect"
|
||||
:value="distance + ''"
|
||||
/>
|
||||
<EditOption
|
||||
:itemIndex="2"
|
||||
:expand="expandIndex === 2"
|
||||
:onExpand="onExpandChange"
|
||||
:onSelect="onSelect"
|
||||
:value="bowtargetType"
|
||||
/>
|
||||
<EditOption
|
||||
:itemIndex="3"
|
||||
|
||||
@@ -3,6 +3,7 @@ import { ref, onMounted } from "vue";
|
||||
import Container from "@/components/Container.vue";
|
||||
import ScreenHint2 from "@/components/ScreenHint2.vue";
|
||||
import SButton from "@/components/SButton.vue";
|
||||
import BowTargetEdit from "@/components/BowTargetEdit.vue";
|
||||
|
||||
const clickable = ref(false);
|
||||
const showTip = ref(false);
|
||||
@@ -39,13 +40,16 @@ const onClickRing = (ring) => {
|
||||
if (arrowGroups.value[currentGroup.value]) {
|
||||
arrowGroups.value[currentGroup.value][currentArrow.value] = ring;
|
||||
clickable.value = arrowGroups.value[currentGroup.value].every(
|
||||
(item) => item !== null
|
||||
(item) => !!item
|
||||
);
|
||||
if (currentArrow.value < amount.value - 1) {
|
||||
currentArrow.value++;
|
||||
}
|
||||
}
|
||||
};
|
||||
const deleteArrow = () => {
|
||||
arrowGroups.value[currentGroup.value][currentArrow.value] = "";
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
const pointBook = uni.getStorageSync("point-book");
|
||||
@@ -53,7 +57,7 @@ onMounted(() => {
|
||||
groups.value = Number(pointBook.amountGroup.split("/")[0]);
|
||||
amount.value = Number(pointBook.amountGroup.split("/")[1]);
|
||||
for (let i = 1; i <= groups.value; i++) {
|
||||
arrowGroups.value[i] = new Array(amount.value).fill(null);
|
||||
arrowGroups.value[i] = new Array(amount.value).fill("");
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -67,13 +71,17 @@ onMounted(() => {
|
||||
:onBack="() => (showTip = true)"
|
||||
>
|
||||
<view class="container">
|
||||
<view class="bow-target">
|
||||
<image src="../static/bow-target.png" mode="widthFix" />
|
||||
</view>
|
||||
<BowTargetEdit />
|
||||
<view class="title-bar">
|
||||
<view>
|
||||
<view />
|
||||
<text>第 {{ currentGroup }} 组</text>
|
||||
</view>
|
||||
<view @click="deleteArrow">
|
||||
<image src="../static/delete.png" />
|
||||
<text>删除</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="bow-arrows">
|
||||
<view
|
||||
v-if="arrowGroups[currentGroup]"
|
||||
@@ -84,12 +92,12 @@ onMounted(() => {
|
||||
borderColor: currentArrow === index ? '#FED847' : '#eeeeee',
|
||||
borderWidth: currentArrow === index ? '2px' : '1px',
|
||||
}"
|
||||
>{{ arrow === null ? "" : arrow + " 环" }}</view
|
||||
>{{ isNaN(arrow) ? arrow : arrow ? arrow + " 环" : "" }}</view
|
||||
>
|
||||
</view>
|
||||
<text>输入分值的情况下,系统不提供落点稳定性分</text>
|
||||
<view class="bow-rings">
|
||||
<view @click="() => onClickRing(11)">X</view>
|
||||
<view @click="() => onClickRing('X')">X</view>
|
||||
<view
|
||||
v-for="i in 10"
|
||||
:key="i"
|
||||
@@ -97,7 +105,7 @@ onMounted(() => {
|
||||
:style="{ backgroundColor: ringColors[i] || '#d8d8d8' }"
|
||||
>{{ 11 - i }}</view
|
||||
>
|
||||
<view @click="() => onClickRing(0)">M</view>
|
||||
<view @click="() => onClickRing('M')">M</view>
|
||||
</view>
|
||||
<ScreenHint2 :show="showTip">
|
||||
<view class="tip-content">
|
||||
@@ -194,27 +202,35 @@ onMounted(() => {
|
||||
.tip-content > view > button:last-child {
|
||||
background: #fed847;
|
||||
}
|
||||
.bow-target {
|
||||
width: 90%;
|
||||
margin: 10px auto;
|
||||
}
|
||||
.bow-target > image {
|
||||
width: 100%;
|
||||
}
|
||||
.title-bar {
|
||||
width: 100%;
|
||||
width: calc(100% - 30px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: 13px;
|
||||
margin: 0 15px;
|
||||
}
|
||||
.title-bar > view:first-child {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
.title-bar > view:first-child {
|
||||
.title-bar > view:first-child > view:first-child {
|
||||
width: 5px;
|
||||
height: 15px;
|
||||
border-radius: 10px;
|
||||
background-color: #fed847;
|
||||
margin-right: 7px;
|
||||
margin-left: 15px;
|
||||
}
|
||||
.title-bar > view:nth-child(2) {
|
||||
color: #287fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.title-bar > view:nth-child(2) image {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 7.8 KiB |
BIN
src/static/delete.png
Normal file
|
After Width: | Height: | Size: 397 B |
BIN
src/static/first-try.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
src/static/friend-battle.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
src/static/my-bow.png
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
src/static/my-growth.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
src/static/my-practise.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 25 KiB |
BIN
src/static/rank-bg.png
Normal file
|
After Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 465 B |
|
Before Width: | Height: | Size: 630 B |
|
Before Width: | Height: | Size: 724 B |
|
Before Width: | Height: | Size: 579 B |
|
Before Width: | Height: | Size: 706 B |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 6.7 KiB |
BIN
src/static/tab-point-book.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |