444 lines
11 KiB
Vue
444 lines
11 KiB
Vue
<script setup>
|
|
import { ref, watch, onMounted, computed } from "vue";
|
|
import { getPointBookConfigAPI } from "@/apis";
|
|
const props = defineProps({
|
|
itemIndex: {
|
|
type: Number,
|
|
default: 0,
|
|
},
|
|
expand: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
onExpand: {
|
|
type: Function,
|
|
default: () => {},
|
|
},
|
|
onSelect: {
|
|
type: Function,
|
|
default: () => {},
|
|
},
|
|
noArrow: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
value: {
|
|
type: String,
|
|
default: "",
|
|
},
|
|
});
|
|
const itemTexts = ["Select Bow", "Select Distance", "Select Target", "Select Sets/Arrows"];
|
|
const distances = [5, 8, 10, 18, 25, 30, 50, 60, 70];
|
|
const groupArrows = [3, 6, 12, 18];
|
|
|
|
const data = ref([]);
|
|
const selectedIndex = ref(-1);
|
|
const secondSelectIndex = ref(-1);
|
|
|
|
const meter = ref("");
|
|
const sets = ref("");
|
|
const arrowAmount = ref("");
|
|
|
|
const onSelectItem = (index) => {
|
|
selectedIndex.value = index;
|
|
if (props.itemIndex === 0) {
|
|
props.onSelect(props.itemIndex, data.value[index]);
|
|
} else if (props.itemIndex === 1) {
|
|
props.onSelect(props.itemIndex, distances[index]);
|
|
} else if (props.itemIndex === 2) {
|
|
props.onSelect(props.itemIndex, data.value[index]);
|
|
} else if (props.itemIndex === 3) {
|
|
if (secondSelectIndex.value !== -1) {
|
|
props.onSelect(
|
|
props.itemIndex,
|
|
`${selectedIndex.value}/${groupArrows[secondSelectIndex.value]}`
|
|
);
|
|
}
|
|
}
|
|
};
|
|
const onSelectSecondItem = (index) => {
|
|
secondSelectIndex.value = index;
|
|
if (selectedIndex.value !== -1) {
|
|
props.onSelect(
|
|
props.itemIndex,
|
|
`${selectedIndex.value < 5 ? selectedIndex.value : sets.value}/${
|
|
groupArrows[secondSelectIndex.value]
|
|
}`
|
|
);
|
|
}
|
|
};
|
|
const onMeterChange = (e) => {
|
|
meter.value = e.detail.value;
|
|
props.onSelect(props.itemIndex, e.detail.value);
|
|
};
|
|
const onSetsChange = (e) => {
|
|
if (!e.detail.value) return;
|
|
sets.value = Math.min(30, Number(e.detail.value));
|
|
if (!sets.value) return;
|
|
if (secondSelectIndex.value !== -1) {
|
|
props.onSelect(
|
|
props.itemIndex,
|
|
`${sets.value}/${
|
|
secondSelectIndex.value === 99
|
|
? arrowAmount.value
|
|
: groupArrows[secondSelectIndex.value]
|
|
}`
|
|
);
|
|
}
|
|
};
|
|
const onArrowAmountChange = (e) => {
|
|
if (!e.detail.value) return;
|
|
arrowAmount.value = Math.min(60, Number(e.detail.value));
|
|
if (!arrowAmount.value) return;
|
|
if (selectedIndex.value !== -1) {
|
|
props.onSelect(
|
|
props.itemIndex,
|
|
`${selectedIndex.value === 99 ? sets.value : selectedIndex.value}/${
|
|
arrowAmount.value
|
|
}`
|
|
);
|
|
}
|
|
};
|
|
watch(
|
|
() => props.value,
|
|
(newValue) => {
|
|
if (!newValue) {
|
|
selectedIndex.value = -1;
|
|
return;
|
|
}
|
|
if (props.itemIndex === 0 || props.itemIndex === 2) {
|
|
data.value.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;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
);
|
|
const loadConfig = () => {
|
|
const config = uni.getStorageSync("point-book-config");
|
|
if (config) {
|
|
if (props.itemIndex === 0) {
|
|
data.value = config.bowOption;
|
|
} else if (props.itemIndex === 2) {
|
|
data.value = config.targetOption;
|
|
}
|
|
if (props.value) {
|
|
if (props.itemIndex === 0 || props.itemIndex === 2) {
|
|
selectedIndex.value = data.value.findIndex(
|
|
(item) => item.name === props.value
|
|
);
|
|
}
|
|
if (props.itemIndex === 1) {
|
|
selectedIndex.value = distances.findIndex(
|
|
(item) => item.name === props.value
|
|
);
|
|
if (selectedIndex.value === -1) {
|
|
selectedIndex.value = 9;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
const formatSetAndAmount = computed(() => {
|
|
if (selectedIndex.value === -1 || secondSelectIndex.value === -1)
|
|
return itemTexts[props.itemIndex];
|
|
if (selectedIndex.value === 99 && !sets.value) return itemTexts[props.itemIndex];
|
|
if (secondSelectIndex.value === 99 && !arrowAmount.value) return itemTexts[props.itemIndex];
|
|
return `${selectedIndex.value === 99 ? sets.value : selectedIndex.value} sets/${
|
|
secondSelectIndex.value === 99
|
|
? arrowAmount.value
|
|
: groupArrows[secondSelectIndex.value]
|
|
} arrows`;
|
|
});
|
|
onMounted(async () => {
|
|
const config = uni.getStorageSync("point-book-config");
|
|
if (config) {
|
|
loadConfig();
|
|
} else {
|
|
const config = await getPointBookConfigAPI();
|
|
uni.setStorageSync("point-book-config", config);
|
|
loadConfig();
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<view
|
|
class="container"
|
|
:style="{
|
|
maxHeight: expand ? '500px' : '50px',
|
|
marginTop: noArrow ? '0' : '10px',
|
|
}"
|
|
>
|
|
<view @click="() => onExpand(itemIndex, !expand)">
|
|
<view></view>
|
|
<block>
|
|
<text v-if="expand" :style="{ color: '#999', fontWeight: 'normal' }">{{
|
|
itemIndex !== 3 ? itemTexts[itemIndex] : "Select Sets"
|
|
}}</text>
|
|
<text v-if="!expand && itemIndex === 0">{{
|
|
value || itemTexts[itemIndex]
|
|
}}</text>
|
|
<text v-if="!expand && itemIndex === 1">{{
|
|
value && value > 0 ? value + " m" : itemTexts[itemIndex]
|
|
}}</text>
|
|
<text v-if="!expand && itemIndex === 2">{{
|
|
value || itemTexts[itemIndex]
|
|
}}</text>
|
|
<text v-if="!expand && itemIndex === 3">{{ formatSetAndAmount }}</text>
|
|
</block>
|
|
<button hover-class="none">
|
|
<image
|
|
v-if="!noArrow"
|
|
src="../static/arrow-grey.png"
|
|
mode="widthFix"
|
|
:style="{ transform: expand ? 'rotateX(180deg)' : 'rotateX(0deg)' }"
|
|
/>
|
|
</button>
|
|
</view>
|
|
<view v-if="itemIndex === 0" class="bow-items">
|
|
<view
|
|
v-for="(item, index) in data"
|
|
:key="index"
|
|
:style="{
|
|
borderColor: selectedIndex === index ? '#fed847' : '#eeeeee',
|
|
}"
|
|
@click="onSelectItem(index)"
|
|
>
|
|
<image :src="item.icon" mode="widthFix" />
|
|
<text>{{ item.name }}</text>
|
|
</view>
|
|
</view>
|
|
<view v-if="itemIndex === 1" class="distance-items">
|
|
<view
|
|
v-for="(item, index) in distances"
|
|
:key="index"
|
|
:style="{
|
|
borderColor: selectedIndex === index ? '#fed847' : '#eeeeee',
|
|
}"
|
|
@click="onSelectItem(index)"
|
|
>
|
|
<text>{{ item }}</text>
|
|
<text>m</text>
|
|
</view>
|
|
<view
|
|
:style="{
|
|
borderColor: selectedIndex === 9 ? '#fed847' : '#eeeeee',
|
|
}"
|
|
>
|
|
<input
|
|
v-model="meter"
|
|
type="number"
|
|
placeholder="Custom"
|
|
placeholder-style="color: #DDDDDD"
|
|
@focus="() => (selectedIndex = 9)"
|
|
@blur="onMeterChange"
|
|
/>
|
|
<text>m</text>
|
|
</view>
|
|
</view>
|
|
<view v-if="itemIndex === 2" class="bowtarget-items">
|
|
<view
|
|
v-for="(item, index) in data"
|
|
:key="index"
|
|
:style="{
|
|
borderColor: selectedIndex === index ? '#fed847' : '#eeeeee',
|
|
}"
|
|
@click="onSelectItem(index)"
|
|
>
|
|
<text>{{ item.name.substring(0, item.name.length - 3) }}</text>
|
|
<text>{{ item.name.substring(item.name.length - 3) }}</text>
|
|
</view>
|
|
</view>
|
|
<view v-if="itemIndex === 3">
|
|
<view class="amount-items">
|
|
<view
|
|
v-for="i in 4"
|
|
:key="i"
|
|
:style="{
|
|
borderColor: selectedIndex === i ? '#fed847' : '#eeeeee',
|
|
}"
|
|
@click="onSelectItem(i)"
|
|
>
|
|
<text>{{ i }}</text>
|
|
<text>sets</text>
|
|
</view>
|
|
<view
|
|
:style="{
|
|
borderColor: selectedIndex === 99 ? '#fed847' : '#eeeeee',
|
|
}"
|
|
>
|
|
<input
|
|
placeholder="1 ~ 30"
|
|
type="number"
|
|
placeholder-style="color: #DDDDDD"
|
|
v-model="sets"
|
|
@focus="() => (selectedIndex = 99)"
|
|
@blur="onSetsChange"
|
|
/>
|
|
<text>sets</text>
|
|
</view>
|
|
</view>
|
|
<view
|
|
:style="{
|
|
marginTop: '5px',
|
|
marginBottom: '10px',
|
|
color: '#999999',
|
|
textAlign: 'center',
|
|
}"
|
|
>Select arrows per set</view
|
|
>
|
|
<view class="amount-items">
|
|
<view
|
|
v-for="(item, index) in groupArrows"
|
|
:key="index"
|
|
:style="{
|
|
borderColor: secondSelectIndex === index ? '#fed847' : '#eeeeee',
|
|
}"
|
|
@click="onSelectSecondItem(index)"
|
|
>
|
|
<text>{{ item }}</text>
|
|
<text>arrows</text>
|
|
</view>
|
|
<view
|
|
:style="{
|
|
borderColor: secondSelectIndex === 99 ? '#fed847' : '#eeeeee',
|
|
}"
|
|
>
|
|
<input
|
|
placeholder="1 ~ 60"
|
|
type="number"
|
|
placeholder-style="color: #DDDDDD"
|
|
v-model="arrowAmount"
|
|
maxlength="99"
|
|
@focus="() => (secondSelectIndex = 99)"
|
|
@blur="onArrowAmountChange"
|
|
/>
|
|
<text>arrows</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.container {
|
|
width: calc(100% - 20px);
|
|
background-color: #fff;
|
|
border-radius: 10px;
|
|
padding: 0 10px;
|
|
font-size: 14px;
|
|
overflow: hidden;
|
|
transition: all 0.3s ease;
|
|
color: #333;
|
|
}
|
|
.container > view:first-child {
|
|
width: 100%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
height: 50px;
|
|
}
|
|
.container > view:first-child > view:first-child {
|
|
width: 85px;
|
|
}
|
|
.container > view:first-child > text:nth-child(2) {
|
|
font-weight: 500;
|
|
}
|
|
.container > view:first-child > button {
|
|
width: 85px;
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
}
|
|
.container > view:first-child > button > image {
|
|
transition: all 0.5s ease;
|
|
width: 16px;
|
|
height: 16px;
|
|
padding-right: 5px;
|
|
}
|
|
.bow-items {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, 1fr);
|
|
column-gap: 2vw;
|
|
}
|
|
.bow-items > view {
|
|
width: 27vw;
|
|
height: 27vw;
|
|
border-radius: 10px;
|
|
border: 2px solid #eeeeee;
|
|
margin-bottom: 2vw;
|
|
}
|
|
.bow-items > view > image {
|
|
width: 100%;
|
|
}
|
|
.bow-items > view > text {
|
|
width: 100%;
|
|
display: block;
|
|
text-align: center;
|
|
transform: translateY(-30px);
|
|
}
|
|
.distance-items,
|
|
.bowtarget-items,
|
|
.amount-items {
|
|
display: grid;
|
|
grid-template-columns: repeat(4, 1fr);
|
|
column-gap: 2vw;
|
|
position: relative;
|
|
}
|
|
.distance-items > view,
|
|
.bowtarget-items > view,
|
|
.amount-items > view {
|
|
width: 20vw;
|
|
height: 12vw;
|
|
border-radius: 10px;
|
|
border: 2px solid #eeeeee;
|
|
margin-bottom: 2vw;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
.distance-items > view > text:first-child,
|
|
.amount-items > view > text:first-child {
|
|
width: 25px;
|
|
display: block;
|
|
text-align: center;
|
|
}
|
|
.distance-items > view:last-child {
|
|
width: 65.5vw;
|
|
position: absolute;
|
|
bottom: 0;
|
|
right: 0;
|
|
}
|
|
.distance-items > view:last-child > input {
|
|
width: 80%;
|
|
text-align: center;
|
|
}
|
|
.bowtarget-items > view {
|
|
flex-direction: column;
|
|
height: 16vw;
|
|
}
|
|
.bowtarget-items > view > text {
|
|
width: 100%;
|
|
text-align: center;
|
|
}
|
|
.amount-items > view:last-child {
|
|
grid-column: 1 / -1;
|
|
width: 100%;
|
|
}
|
|
.amount-items > view:last-child > input {
|
|
width: 85%;
|
|
text-align: center;
|
|
}
|
|
</style>
|