mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2026-03-15 03:53:16 +08:00
♻️ 重构WIKI筛选组件筛选逻辑
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
<!-- 角色筛选 -->
|
||||
<template>
|
||||
<TOverlay v-model="visible">
|
||||
<div class="two-sc-container">
|
||||
<div class="two-sc-item">
|
||||
<div class="two-sc-title">星级</div>
|
||||
<v-item-group multiple mandatory v-model="selectedStar" class="two-sc-select">
|
||||
<v-item-group v-model="selectedStar" class="two-sc-select" multiple>
|
||||
<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-btn :color="isSelected ? 'primary' : ''" @click="toggle">
|
||||
<v-icon>{{ isSelected ? "mdi-star" : "mdi-star-outline" }}</v-icon>
|
||||
<span>{{ item }}星</span>
|
||||
</v-btn>
|
||||
@@ -16,10 +17,10 @@
|
||||
</div>
|
||||
<div class="two-sc-item">
|
||||
<div class="two-sc-title">武器</div>
|
||||
<v-item-group multiple mandatory v-model="selectedWeapon" class="two-sc-select">
|
||||
<v-item-group v-model="selectedWeapon" class="two-sc-select" multiple>
|
||||
<div v-for="(item, index) in selectWeaponList" :key="index">
|
||||
<v-item v-slot="{ isSelected, toggle }" :value="item">
|
||||
<v-btn @click="toggle" :color="isSelected ? 'primary' : ''">
|
||||
<v-btn :color="isSelected ? 'primary' : ''" @click="toggle">
|
||||
<img :alt="`${item}`" :src="`/icon/weapon/${item}.webp`" class="two-sci-icon" />
|
||||
<span>{{ item }}</span>
|
||||
</v-btn>
|
||||
@@ -29,10 +30,10 @@
|
||||
</div>
|
||||
<div class="two-sc-item">
|
||||
<div class="two-sc-title">元素</div>
|
||||
<v-item-group multiple mandatory v-model="selectedElements" class="two-sc-select">
|
||||
<v-item-group v-model="selectedElements" class="two-sc-select" multiple>
|
||||
<div v-for="(item, index) in selectElementList" :key="index">
|
||||
<v-item v-slot="{ isSelected, toggle }" :value="item">
|
||||
<v-btn @click="toggle" class="element-btn" :color="isSelected ? 'primary' : ''">
|
||||
<v-btn :color="isSelected ? 'primary' : ''" class="element-btn" @click="toggle">
|
||||
<img
|
||||
:alt="`${item}元素`"
|
||||
:src="`/icon/element/${item}元素.webp`"
|
||||
@@ -46,10 +47,10 @@
|
||||
</div>
|
||||
<div class="two-sc-item">
|
||||
<div class="two-sc-title">阵营</div>
|
||||
<v-item-group multiple mandatory v-model="selectedArea" class="two-sc-select">
|
||||
<v-item-group v-model="selectedArea" class="two-sc-select" multiple>
|
||||
<div v-for="(item, index) in selectAreaList" :key="index">
|
||||
<v-item v-slot="{ isSelected, toggle }" :value="item">
|
||||
<v-btn @click="toggle" :color="isSelected ? 'primary' : ''">
|
||||
<v-btn :color="isSelected ? 'primary' : ''" @click="toggle">
|
||||
<v-icon>{{ isSelected ? "mdi-check" : "mdi-checkbox-blank-outline" }}</v-icon>
|
||||
<span>{{ item }}</span>
|
||||
</v-btn>
|
||||
@@ -64,10 +65,10 @@
|
||||
</div>
|
||||
</TOverlay>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import TOverlay from "@comp/app/t-overlay.vue";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import { ref, toRaw, watch } from "vue";
|
||||
import { ref, shallowRef, watch } from "vue";
|
||||
|
||||
export type SelectedCValue = {
|
||||
star: Array<number>;
|
||||
@@ -97,11 +98,16 @@ const selectAreaList = [
|
||||
"挪德卡莱",
|
||||
];
|
||||
|
||||
// 选中的元素
|
||||
const selectedStar = ref<Array<number>>(selectStarList);
|
||||
const selectedWeapon = ref<Array<string>>(selectWeaponList);
|
||||
const selectedElements = ref<Array<string>>(selectElementList);
|
||||
const selectedArea = ref<Array<string>>(selectAreaList);
|
||||
const selectedStar = ref<Array<number>>([]);
|
||||
const selectedWeapon = ref<Array<string>>([]);
|
||||
const selectedElements = ref<Array<string>>([]);
|
||||
const selectedArea = ref<Array<string>>([]);
|
||||
const oldVal = shallowRef<SelectedCValue>({
|
||||
star: selectedStar.value,
|
||||
weapon: selectedWeapon.value,
|
||||
elements: selectedElements.value,
|
||||
area: selectedArea.value,
|
||||
});
|
||||
const visible = defineModel<boolean>();
|
||||
const resetModel = defineModel<boolean>("reset");
|
||||
|
||||
@@ -110,25 +116,47 @@ watch(
|
||||
() => {
|
||||
if (resetModel.value) {
|
||||
if (
|
||||
toRaw(selectedStar.value) === selectStarList &&
|
||||
toRaw(selectedWeapon.value) === selectWeaponList &&
|
||||
toRaw(selectedElements.value) === selectElementList &&
|
||||
toRaw(selectedArea.value) === selectAreaList
|
||||
isNotFilter(selectedStar.value, selectStarList) &&
|
||||
isNotFilter(selectedWeapon.value, selectWeaponList) &&
|
||||
isNotFilter(selectedElements.value, selectElementList) &&
|
||||
isNotFilter(selectedArea.value, selectAreaList)
|
||||
) {
|
||||
showSnackbar.warn("无需重置");
|
||||
resetModel.value = false;
|
||||
return;
|
||||
}
|
||||
selectedStar.value = selectStarList;
|
||||
selectedWeapon.value = selectWeaponList;
|
||||
selectedElements.value = selectElementList;
|
||||
selectedArea.value = selectAreaList;
|
||||
selectedStar.value = [];
|
||||
selectedWeapon.value = [];
|
||||
selectedElements.value = [];
|
||||
selectedArea.value = [];
|
||||
oldVal.value = {
|
||||
star: selectedStar.value,
|
||||
weapon: selectedWeapon.value,
|
||||
elements: selectedElements.value,
|
||||
area: selectedArea.value,
|
||||
};
|
||||
resetModel.value = false;
|
||||
showSnackbar.success("已重置");
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
watch(
|
||||
() => visible.value,
|
||||
() => {
|
||||
if (visible.value) {
|
||||
selectedStar.value = oldVal.value.star;
|
||||
selectedWeapon.value = oldVal.value.weapon;
|
||||
selectedArea.value = oldVal.value.area;
|
||||
selectedElements.value = oldVal.value.elements;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
function isNotFilter<T>(list: Array<T>, data: Array<T>): boolean {
|
||||
return list.length === 0 || list.length === data.length;
|
||||
}
|
||||
|
||||
function confirmSelect() {
|
||||
const value: SelectedCValue = {
|
||||
star: selectedStar.value,
|
||||
@@ -137,6 +165,7 @@ function confirmSelect() {
|
||||
area: selectedArea.value,
|
||||
};
|
||||
emits("select-c", value);
|
||||
oldVal.value = value;
|
||||
visible.value = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
<!-- 武器筛选 -->
|
||||
<template>
|
||||
<TOverlay v-model="visible">
|
||||
<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">
|
||||
<v-item-group v-model="selectedStar" class="two-sw-select" mandatory multiple>
|
||||
<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-btn :color="isSelected ? 'primary' : ''" @click="toggle">
|
||||
<v-icon>{{ isSelected ? "mdi-star" : "mdi-star-outline" }}</v-icon>
|
||||
<span>{{ item }}星</span>
|
||||
</v-btn>
|
||||
@@ -16,10 +17,10 @@
|
||||
</div>
|
||||
<div class="two-sw-item">
|
||||
<div class="two-sw-title">武器</div>
|
||||
<v-item-group multiple mandatory v-model="selectedWeapon" class="two-sw-select">
|
||||
<v-item-group v-model="selectedWeapon" class="two-sw-select" mandatory multiple>
|
||||
<div v-for="(item, index) in selectWeaponList" :key="index">
|
||||
<v-item v-slot="{ isSelected, toggle }" :value="item">
|
||||
<v-btn @click="toggle" :color="isSelected ? 'primary' : ''">
|
||||
<v-btn :color="isSelected ? 'primary' : ''" @click="toggle">
|
||||
<img :alt="`${item}元素`" :src="`/icon/weapon/${item}.webp`" class="two-swi-icon" />
|
||||
<span>{{ item }}</span>
|
||||
</v-btn>
|
||||
@@ -34,12 +35,12 @@
|
||||
</div>
|
||||
</TOverlay>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import TOverlay from "@comp/app/t-overlay.vue";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import { ref, toRaw, watch } from "vue";
|
||||
import { ref, shallowRef, watch } from "vue";
|
||||
|
||||
export type SelectedWValue = { star: Array<number>; weapon: Array<string>; isReset: boolean };
|
||||
export type SelectedWValue = { star: Array<number>; weapon: Array<string> };
|
||||
type TwoSelectWEmits = (e: "select-w", value: SelectedWValue) => void;
|
||||
|
||||
const emits = defineEmits<TwoSelectWEmits>();
|
||||
@@ -47,8 +48,12 @@ const emits = defineEmits<TwoSelectWEmits>();
|
||||
const selectStarList = [4, 5];
|
||||
const selectWeaponList = ["单手剑", "双手剑", "弓", "法器", "长柄武器"];
|
||||
|
||||
const selectedStar = ref<Array<number>>(selectStarList);
|
||||
const selectedWeapon = ref<Array<string>>(selectWeaponList);
|
||||
const selectedStar = ref<Array<number>>([]);
|
||||
const selectedWeapon = ref<Array<string>>([]);
|
||||
const oldVal = shallowRef<SelectedWValue>({
|
||||
star: selectedStar.value,
|
||||
weapon: selectedWeapon.value,
|
||||
});
|
||||
const visible = defineModel<boolean>();
|
||||
const resetModel = defineModel<boolean>("reset");
|
||||
|
||||
@@ -57,23 +62,43 @@ watch(
|
||||
() => {
|
||||
if (resetModel.value) {
|
||||
if (
|
||||
toRaw(selectedStar.value) === selectStarList &&
|
||||
toRaw(selectedWeapon.value) === selectWeaponList
|
||||
isNotFilter(selectedStar.value, selectStarList) &&
|
||||
isNotFilter(selectedWeapon.value, selectWeaponList)
|
||||
) {
|
||||
showSnackbar.warn("无需重置");
|
||||
resetModel.value = false;
|
||||
return;
|
||||
}
|
||||
selectedStar.value = selectStarList;
|
||||
selectedWeapon.value = selectWeaponList;
|
||||
selectedStar.value = [];
|
||||
selectedWeapon.value = [];
|
||||
oldVal.value = {
|
||||
star: selectedStar.value,
|
||||
weapon: selectedWeapon.value,
|
||||
};
|
||||
resetModel.value = false;
|
||||
emits("select-w", { star: selectedStar.value, weapon: selectedWeapon.value, isReset: true });
|
||||
showSnackbar.success("已重置");
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
watch(
|
||||
() => visible.value,
|
||||
() => {
|
||||
if (visible.value) {
|
||||
selectedStar.value = oldVal.value.star;
|
||||
selectedWeapon.value = oldVal.value.weapon;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
function isNotFilter<T>(list: Array<T>, data: Array<T>): boolean {
|
||||
return list.length === 0 || list.length === data.length;
|
||||
}
|
||||
|
||||
function confirmSelect(): void {
|
||||
emits("select-w", { star: selectedStar.value, weapon: selectedWeapon.value, isReset: false });
|
||||
const value: SelectedWValue = { star: selectedStar.value, weapon: selectedWeapon.value };
|
||||
emits("select-w", value);
|
||||
oldVal.value = value;
|
||||
visible.value = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -77,17 +77,17 @@ onBeforeMount(() => {
|
||||
watch(
|
||||
() => resetSelect.value,
|
||||
(val) => {
|
||||
if (val) cardsInfo.value = AppCharacterData;
|
||||
if (val) cardsInfo.value = appCData;
|
||||
},
|
||||
);
|
||||
|
||||
function handleSelect(val: SelectedCValue): void {
|
||||
showSelect.value = false;
|
||||
const filterC = AppCharacterData.filter((item) => {
|
||||
if (!val.star.includes(item.star)) return false;
|
||||
if (!val.weapon.includes(item.weapon)) return false;
|
||||
if (!val.elements.includes(item.element)) return false;
|
||||
return val.area.includes(item.area);
|
||||
if (val.star.length > 0 && !val.star.includes(item.star)) return false;
|
||||
if (val.weapon.length > 0 && !val.weapon.includes(item.weapon)) return false;
|
||||
if (val.elements.length > 0 && !val.elements.includes(item.element)) return false;
|
||||
return !(val.area.length > 0 && val.area.includes(item.area));
|
||||
});
|
||||
if (filterC.length === 0) {
|
||||
showSnackbar.warn("未找到符合条件的角色");
|
||||
@@ -134,6 +134,7 @@ async function toOuter(item?: TGApp.App.Character.WikiBriefInfo): Promise<void>
|
||||
}
|
||||
|
||||
.wc-left {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: fit-content;
|
||||
flex-direction: column;
|
||||
@@ -161,11 +162,11 @@ async function toOuter(item?: TGApp.App.Character.WikiBriefInfo): Promise<void>
|
||||
.wc-list {
|
||||
position: relative;
|
||||
display: grid;
|
||||
overflow: hidden auto;
|
||||
width: 100%;
|
||||
padding-right: 8px;
|
||||
gap: 8px;
|
||||
grid-template-columns: repeat(3, 160px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.wc-detail {
|
||||
|
||||
@@ -30,12 +30,12 @@ import TwcListItem from "@comp/pageWiki/twc-list-item.vue";
|
||||
import TwcWeapon from "@comp/pageWiki/twc-weapon.vue";
|
||||
import TwoSelectW, { type SelectedWValue } from "@comp/pageWiki/two-select-w.vue";
|
||||
import { toObcPage } from "@utils/TGWindow.js";
|
||||
import { onBeforeMount, ref, shallowRef } from "vue";
|
||||
import { onBeforeMount, ref, shallowRef, watch } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
import { AppWeaponData } from "@/data/index.js";
|
||||
|
||||
const sortedData = AppWeaponData.sort((a, b) => {
|
||||
const appWData = AppWeaponData.sort((a, b) => {
|
||||
if (a.star !== b.star) return b.star - a.star;
|
||||
if (a.weapon !== b.weapon) return a.weapon.localeCompare(b.weapon);
|
||||
return b.id - a.id;
|
||||
@@ -44,7 +44,7 @@ const sortedData = AppWeaponData.sort((a, b) => {
|
||||
const id = useRoute().params.id.toString() ?? "0";
|
||||
const showSelect = ref<boolean>(false);
|
||||
const resetSelect = ref<boolean>(false);
|
||||
const cardsInfo = shallowRef<Array<TGApp.App.Weapon.WikiBriefInfo>>(sortedData);
|
||||
const cardsInfo = shallowRef<Array<TGApp.App.Weapon.WikiBriefInfo>>(appWData);
|
||||
const curItem = shallowRef<TGApp.App.Weapon.WikiBriefInfo>({
|
||||
id: 0,
|
||||
contentId: 0,
|
||||
@@ -67,15 +67,24 @@ onBeforeMount(() => {
|
||||
curItem.value = cardsInfo.value[0];
|
||||
});
|
||||
|
||||
watch(
|
||||
() => resetSelect.value,
|
||||
() => {
|
||||
if (resetSelect.value) {
|
||||
cardsInfo.value = appWData;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
function switchW(item: TGApp.App.Weapon.WikiBriefInfo): void {
|
||||
curItem.value = item;
|
||||
}
|
||||
|
||||
function handleSelectW(val: SelectedWValue) {
|
||||
if (!val.isReset) showSelect.value = true;
|
||||
showSelect.value = false;
|
||||
const filterW = AppWeaponData.filter((item) => {
|
||||
if (!val.star.includes(item.star)) return false;
|
||||
return val.weapon.includes(item.weapon);
|
||||
if (val.star.length > 0 && !val.star.includes(item.star)) return false;
|
||||
return !(val.weapon.length > 0 && !val.weapon.includes(item.weapon));
|
||||
});
|
||||
if (filterW.length === 0) {
|
||||
showSnackbar.warn("未找到符合条件的武器");
|
||||
@@ -139,7 +148,7 @@ async function toOuter(item?: TGApp.App.Weapon.WikiBriefInfo): Promise<void> {
|
||||
padding-right: 8px;
|
||||
gap: 8px;
|
||||
grid-template-columns: repeat(3, 160px);
|
||||
overflow-y: auto;
|
||||
overflow: hidden auto;
|
||||
}
|
||||
|
||||
.ww-detail {
|
||||
|
||||
Reference in New Issue
Block a user