mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-11 09:08:14 +08:00
156
src/components/wiki/two-select-w.vue
Normal file
156
src/components/wiki/two-select-w.vue
Normal file
@@ -0,0 +1,156 @@
|
||||
<template>
|
||||
<TOverlay v-model="visible" hide :to-click="onCancel" blur-val="20px">
|
||||
<div class="two-sw-container">
|
||||
<div class="two-sw-item">
|
||||
<div class="two-sw-title">星级</div>
|
||||
<v-item-group multiple mandatory v-model="selectedStar" class="two-sw-select">
|
||||
<div v-for="(item, index) in selectStarList" :key="index">
|
||||
<v-item v-slot="{ isSelected, toggle }" :value="item">
|
||||
<v-btn @click="toggle" :color="isSelected ? 'primary' : ''">
|
||||
<v-icon>{{ isSelected ? "mdi-star" : "mdi-star-outline" }}</v-icon>
|
||||
<span>{{ item }}星</span>
|
||||
</v-btn>
|
||||
</v-item>
|
||||
</div>
|
||||
</v-item-group>
|
||||
</div>
|
||||
<div class="two-sw-item">
|
||||
<div class="two-sw-title">武器</div>
|
||||
<v-item-group multiple mandatory v-model="selectedWeapon" class="two-sw-select">
|
||||
<div v-for="(item, index) in selectWeaponList" :key="index">
|
||||
<v-item v-slot="{ isSelected, toggle }" :value="item">
|
||||
<v-btn @click="toggle" :color="isSelected ? 'primary' : ''">
|
||||
<img :alt="`${item}元素`" :src="`/icon/weapon/${item}.webp`" class="two-swi-icon" />
|
||||
<span>{{ item }}</span>
|
||||
</v-btn>
|
||||
</v-item>
|
||||
</div>
|
||||
</v-item-group>
|
||||
</div>
|
||||
<div class="tow-sc-submit">
|
||||
<v-btn variant="tonal" @click="onCancel">取消</v-btn>
|
||||
<v-btn @click="confirmSelect">确定</v-btn>
|
||||
</div>
|
||||
</div>
|
||||
</TOverlay>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from "vue";
|
||||
|
||||
import TOverlay from "../main/t-overlay.vue";
|
||||
|
||||
// 一些数据
|
||||
const selectStarList = [4, 5];
|
||||
const selectWeaponList = ["单手剑", "双手剑", "弓", "法器", "长柄武器"];
|
||||
|
||||
// 选中的元素
|
||||
const selectedStar = ref<number[]>(selectStarList);
|
||||
const selectedWeapon = ref<string[]>(selectWeaponList);
|
||||
|
||||
export interface SelectedWValue {
|
||||
star: number[];
|
||||
weapon: string[];
|
||||
}
|
||||
|
||||
interface TwoSelectWProps {
|
||||
modelValue: boolean;
|
||||
reset: boolean;
|
||||
}
|
||||
|
||||
interface TwoSelectWEmits {
|
||||
(e: "update:modelValue", value: boolean): void;
|
||||
|
||||
(e: "update:reset", value: boolean): void;
|
||||
|
||||
(e: "select-w", value: SelectedWValue): void;
|
||||
}
|
||||
|
||||
const props = defineProps<TwoSelectWProps>();
|
||||
const emits = defineEmits<TwoSelectWEmits>();
|
||||
|
||||
const visible = computed({
|
||||
get() {
|
||||
return props.modelValue;
|
||||
},
|
||||
set(value) {
|
||||
emits("update:modelValue", value);
|
||||
},
|
||||
});
|
||||
const reset = computed({
|
||||
get() {
|
||||
return props.reset;
|
||||
},
|
||||
set(value) {
|
||||
emits("update:reset", value);
|
||||
},
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.reset,
|
||||
(value) => {
|
||||
if (value) {
|
||||
selectedStar.value = selectStarList;
|
||||
selectedWeapon.value = selectWeaponList;
|
||||
reset.value = false;
|
||||
confirmSelect();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
function onCancel() {
|
||||
visible.value = false;
|
||||
}
|
||||
|
||||
function confirmSelect() {
|
||||
const value: SelectedWValue = {
|
||||
star: selectedStar.value,
|
||||
weapon: selectedWeapon.value,
|
||||
};
|
||||
emits("select-w", value);
|
||||
visible.value = false;
|
||||
}
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.two-sw-container {
|
||||
display: flex;
|
||||
width: 400px;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
background-color: var(--box-bg-1);
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.two-sw-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: flex-start;
|
||||
column-gap: 10px;
|
||||
}
|
||||
|
||||
.two-sw-title {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
word-break: keep-all;
|
||||
}
|
||||
|
||||
.two-sw-select {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.two-swi-icon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.tow-sc-submit {
|
||||
display: flex;
|
||||
margin-left: auto;
|
||||
gap: 10px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,19 +1,28 @@
|
||||
<template>
|
||||
<div class="ww-box">
|
||||
<div class="ww-list">
|
||||
<TwcListItem
|
||||
v-for="item in cardsInfo"
|
||||
v-model:cur-item="curItem"
|
||||
:key="item.id"
|
||||
:data="item"
|
||||
@click="switchW(item)"
|
||||
mode="weapon"
|
||||
/>
|
||||
<div class="ww-left">
|
||||
<div class="ww-select">
|
||||
<v-btn @click="showSelect = true">
|
||||
<span>筛选武器</span>
|
||||
</v-btn>
|
||||
<v-btn @click="resetSelect = true">重置筛选</v-btn>
|
||||
</div>
|
||||
<div class="ww-list">
|
||||
<TwcListItem
|
||||
v-for="(item, index) in cardsInfo"
|
||||
v-model:cur-item="curItem"
|
||||
:key="index"
|
||||
:data="item"
|
||||
@click="switchW(item)"
|
||||
mode="weapon"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ww-detail">
|
||||
<TwcWeapon :item="curItem" @error="toOuter(curItem)" />
|
||||
</div>
|
||||
</div>
|
||||
<TwoSelectW v-model="showSelect" @select-w="handleSelectW" v-model:reset="resetSelect" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@@ -24,19 +33,22 @@ import showConfirm from "../../components/func/confirm";
|
||||
import showSnackbar from "../../components/func/snackbar";
|
||||
import TwcListItem from "../../components/wiki/twc-list-item.vue";
|
||||
import TwcWeapon from "../../components/wiki/twc-weapon.vue";
|
||||
import TwoSelectW, { SelectedWValue } from "../../components/wiki/two-select-w.vue";
|
||||
import { AppWeaponData } from "../../data";
|
||||
import Mys from "../../plugins/Mys";
|
||||
import { createTGWindow } from "../../utils/TGWindow";
|
||||
|
||||
const id = useRoute().params.id.toString() ?? "0";
|
||||
const cardsInfo = AppWeaponData;
|
||||
const showSelect = ref(false);
|
||||
const resetSelect = ref(false);
|
||||
const cardsInfo = ref(AppWeaponData);
|
||||
const curItem = ref<TGApp.App.Weapon.WikiBriefInfo>();
|
||||
|
||||
onBeforeMount(() => {
|
||||
if (id === "0") {
|
||||
curItem.value = cardsInfo[0];
|
||||
curItem.value = cardsInfo.value[0];
|
||||
} else {
|
||||
const item = cardsInfo.find((item) => item.id.toString() === id);
|
||||
const item = cardsInfo.value.find((item) => item.id.toString() === id);
|
||||
if (item) {
|
||||
curItem.value = item;
|
||||
} else {
|
||||
@@ -44,11 +56,31 @@ onBeforeMount(() => {
|
||||
text: `武器 ${id} 不存在`,
|
||||
color: "warn",
|
||||
});
|
||||
curItem.value = cardsInfo[0];
|
||||
curItem.value = cardsInfo.value[0];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function handleSelectW(val: SelectedWValue) {
|
||||
showSelect.value = true;
|
||||
const reg = /\/icon\/weapon\/(.+?)\.webp/;
|
||||
const filterW = AppWeaponData.filter((item) => {
|
||||
if (!val.star.includes(item.star)) return false;
|
||||
return val.weapon.includes(item.weaponIcon.match(reg)![1]);
|
||||
});
|
||||
if (filterW.length === 0) {
|
||||
showSnackbar({
|
||||
text: "未找到符合条件的武器",
|
||||
color: "warn",
|
||||
});
|
||||
return;
|
||||
}
|
||||
showSnackbar({
|
||||
text: `找到 ${filterW.length} 件符合条件的武器`,
|
||||
});
|
||||
cardsInfo.value = filterW;
|
||||
}
|
||||
|
||||
async function switchW(item: TGApp.App.Weapon.WikiBriefInfo): Promise<void> {
|
||||
curItem.value = item;
|
||||
}
|
||||
@@ -85,12 +117,29 @@ async function toOuter(item?: TGApp.App.Weapon.WikiBriefInfo): Promise<void> {
|
||||
column-gap: 10px;
|
||||
}
|
||||
|
||||
.ww-left {
|
||||
display: flex;
|
||||
width: 500px;
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.ww-select {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.ww-list {
|
||||
position: relative;
|
||||
display: grid;
|
||||
width: 500px;
|
||||
max-height: 100%;
|
||||
height: calc(100% - 40px);
|
||||
padding-right: 10px;
|
||||
gap: 10px;
|
||||
grid-auto-rows: 45px;
|
||||
grid-template-columns: repeat(3, minmax(100px, 1fr));
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user