mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-12 09:18:14 +08:00
♻️ 角色使用率&出场率
This commit is contained in:
@@ -13,7 +13,11 @@
|
||||
:value="selectItem.Floor.toString()"
|
||||
>
|
||||
<div class="hta-tu-grid">
|
||||
<TibWikiAbyss v-for="item in selectItem.Ranks" :key="item.Item" :model-value="item" />
|
||||
<TibWikiAbyss
|
||||
v-for="(item, index) in selectItem.Ranks"
|
||||
:key="index"
|
||||
:model-value="item"
|
||||
/>
|
||||
</div>
|
||||
</v-window-item>
|
||||
</v-window>
|
||||
@@ -22,30 +26,47 @@
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from "vue";
|
||||
|
||||
import { AbyssDataItem } from "../../pages/WIKI/Abyss.vue";
|
||||
import TibWikiAbyss from "../itembox/tib-wiki-abyss.vue";
|
||||
|
||||
interface HtaTabUseProps {
|
||||
modelValue: TGApp.Plugins.Hutao.Abyss.AvatarUp[];
|
||||
interface HtaTabUpProps {
|
||||
data: AbyssDataItem<TGApp.Plugins.Hutao.Abyss.AvatarUse[]>;
|
||||
}
|
||||
|
||||
const props = defineProps<HtaTabUseProps>();
|
||||
interface HtaTabUpData {
|
||||
Floor: number;
|
||||
Ranks: Array<AbyssDataItem<{ Item: number; Rate: number }>>;
|
||||
}
|
||||
|
||||
const props = defineProps<HtaTabUpProps>();
|
||||
|
||||
// data
|
||||
const tab = ref<string>("9");
|
||||
const select = ref<TGApp.Plugins.Hutao.Abyss.AvatarUp[]>([]);
|
||||
const select = ref<Array<HtaTabUpData>>([]);
|
||||
|
||||
onMounted(async () => {
|
||||
props.modelValue.forEach((item) => {
|
||||
item.Ranks.sort((a, b) => b.Rate - a.Rate);
|
||||
select.value.push(item);
|
||||
});
|
||||
for (const floor of props.data.cur) {
|
||||
const floorLast = props.data.last.find((f) => f.Floor === floor.Floor);
|
||||
const floorRank = {
|
||||
Floor: floor.Floor,
|
||||
Ranks: <Array<AbyssDataItem<{ Item: number; Rate: number }>>>[],
|
||||
};
|
||||
floor.Ranks.sort((a, b) => b.Rate - a.Rate);
|
||||
for (const rank of floor.Ranks) {
|
||||
const rankLast = floorLast?.Ranks.find((r) => r.Item === rank.Item);
|
||||
floorRank.Ranks.push({
|
||||
cur: rank,
|
||||
last: rankLast ?? { Item: rank.Item, Rate: 0 },
|
||||
});
|
||||
}
|
||||
select.value.push(floorRank);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.hta-tu-box {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
padding-top: 10px;
|
||||
column-gap: 10px;
|
||||
}
|
||||
|
||||
@@ -63,11 +84,11 @@ onMounted(async () => {
|
||||
display: grid;
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-height: calc(100vh - 100px);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 5px;
|
||||
grid-gap: 5px;
|
||||
grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
|
||||
padding: 10px;
|
||||
grid-gap: 10px;
|
||||
grid-template-columns: repeat(auto-fill, minmax(180px, 0.2fr));
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -13,7 +13,11 @@
|
||||
:value="selectItem.Floor.toString()"
|
||||
>
|
||||
<div class="hta-tus-grid">
|
||||
<TibWikiAbyss v-for="item in selectItem.Ranks" :key="item.Item" :model-value="item" />
|
||||
<TibWikiAbyss
|
||||
v-for="(item, index) in selectItem.Ranks"
|
||||
:key="index"
|
||||
:model-value="item"
|
||||
/>
|
||||
</div>
|
||||
</v-window-item>
|
||||
</v-window>
|
||||
@@ -22,35 +26,51 @@
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from "vue";
|
||||
|
||||
import { AbyssDataItem } from "../../pages/WIKI/Abyss.vue";
|
||||
import TibWikiAbyss from "../itembox/tib-wiki-abyss.vue";
|
||||
|
||||
interface HtaTabUseProps {
|
||||
modelValue: TGApp.Plugins.Hutao.Abyss.AvatarUse[];
|
||||
data: AbyssDataItem<TGApp.Plugins.Hutao.Abyss.AvatarUse[]>;
|
||||
}
|
||||
|
||||
interface HtaTabUseData {
|
||||
Floor: number;
|
||||
Ranks: Array<AbyssDataItem<{ Item: number; Rate: number }>>;
|
||||
}
|
||||
|
||||
const props = defineProps<HtaTabUseProps>();
|
||||
|
||||
// data
|
||||
const tab = ref<string>("9");
|
||||
const select = ref<TGApp.Plugins.Hutao.Abyss.AvatarUse[]>([]);
|
||||
const select = ref<Array<HtaTabUseData>>([]);
|
||||
|
||||
onMounted(async () => {
|
||||
props.modelValue.forEach((item) => {
|
||||
item.Ranks.sort((a, b) => b.Rate - a.Rate);
|
||||
select.value.push(item);
|
||||
});
|
||||
for (const floor of props.data.cur) {
|
||||
const floorLast = props.data.last.find((f) => f.Floor === floor.Floor);
|
||||
const floorRank = {
|
||||
Floor: floor.Floor,
|
||||
Ranks: <Array<AbyssDataItem<{ Item: number; Rate: number }>>>[],
|
||||
};
|
||||
floor.Ranks.sort((a, b) => b.Rate - a.Rate);
|
||||
for (const rank of floor.Ranks) {
|
||||
const rankLast = floorLast?.Ranks.find((r) => r.Item === rank.Item);
|
||||
floorRank.Ranks.push({
|
||||
cur: rank,
|
||||
last: rankLast ?? { Item: rank.Item, Rate: 0 },
|
||||
});
|
||||
}
|
||||
select.value.push(floorRank);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.hta-tus-box {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
padding-top: 10px;
|
||||
column-gap: 10px;
|
||||
}
|
||||
|
||||
.hta-tus-tab {
|
||||
width: 100px;
|
||||
height: 100%;
|
||||
color: var(--box-text-4);
|
||||
}
|
||||
@@ -64,11 +84,11 @@ onMounted(async () => {
|
||||
display: grid;
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-height: calc(100vh - 100px);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 5px;
|
||||
grid-gap: 5px;
|
||||
grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
|
||||
padding: 10px;
|
||||
grid-gap: 10px;
|
||||
grid-template-columns: repeat(auto-fill, minmax(180px, 0.2fr));
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,46 +1,95 @@
|
||||
<template>
|
||||
<TItemBox :model-value="box" />
|
||||
<div class="twa-container">
|
||||
<TItemBox :model-value="box" />
|
||||
<div class="twa-diff">
|
||||
<span>{{ avatar?.name ?? "旅行者" }}</span>
|
||||
<span>{{ `${(props.modelValue.cur.Rate * 100).toFixed(3)}%` }}</span>
|
||||
<span :class="diffUp ? 'up' : 'down'">{{ getDiffStr() }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed } from "vue";
|
||||
|
||||
import { AppCharacterData } from "../../data/index.js";
|
||||
import { AbyssDataItem } from "../../pages/WIKI/Abyss.vue";
|
||||
import TItemBox, { type TItemBoxData } from "../main/t-itembox.vue";
|
||||
|
||||
interface TibWikiAbyssProps {
|
||||
modelValue: {
|
||||
Item: number;
|
||||
Rate: number;
|
||||
};
|
||||
modelValue: AbyssDataItem<{ Item: number; Rate: number }>;
|
||||
}
|
||||
|
||||
const props = defineProps<TibWikiAbyssProps>();
|
||||
|
||||
const avatar = ref<TGApp.App.Character.WikiBriefInfo>();
|
||||
const diffUp = computed(() => props.modelValue.cur.Rate > props.modelValue.last.Rate);
|
||||
|
||||
const box = computed<TItemBoxData>(() => {
|
||||
return {
|
||||
bg: `/icon/bg/${avatar.value?.star}-Star.webp`,
|
||||
clickable: false,
|
||||
display: "outer",
|
||||
height: "100px",
|
||||
display: "inner",
|
||||
icon: `/WIKI/character/${avatar.value?.id}.webp`,
|
||||
innerHeight: 20,
|
||||
innerText: (props.modelValue.Rate * 100).toFixed(3) + "%",
|
||||
innerHeight: 0,
|
||||
innerText: avatar.value?.name ?? "旅行者",
|
||||
lt:
|
||||
avatar.value === undefined
|
||||
? ""
|
||||
: avatar.value.element !== ""
|
||||
? `/icon/element/${avatar.value.element}元素.webp`
|
||||
: `/icon/weapon/${avatar.value.weapon}.webp`,
|
||||
ltSize: "20px",
|
||||
outerHeight: 20,
|
||||
outerText: avatar.value?.name ?? "旅行者",
|
||||
size: "80px",
|
||||
ltSize: "15px",
|
||||
size: "60px",
|
||||
height: "60px",
|
||||
};
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
avatar.value = AppCharacterData.find((a) => a.id === props.modelValue.Item);
|
||||
avatar.value = AppCharacterData.find((a) => a.id === props.modelValue.cur.Item);
|
||||
});
|
||||
|
||||
function getDiffStr() {
|
||||
if (props.modelValue.cur.Rate === props.modelValue.last.Rate) return "";
|
||||
if (props.modelValue.last.Rate > props.modelValue.cur.Rate) {
|
||||
return `↓${((props.modelValue.last.Rate - props.modelValue.cur.Rate) * 100).toFixed(3)}%`;
|
||||
}
|
||||
return `↑${((props.modelValue.cur.Rate - props.modelValue.last.Rate) * 100).toFixed(3)}%`;
|
||||
}
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.twa-container {
|
||||
display: flex;
|
||||
height: 60px;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
border: 1px solid var(--common-shadow-2);
|
||||
border-radius: 5px;
|
||||
background: var(--box-bg-1);
|
||||
column-gap: 5px;
|
||||
}
|
||||
|
||||
.twa-diff {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
color: var(--box-text-4);
|
||||
font-size: 12px;
|
||||
|
||||
:first-child {
|
||||
font-family: var(--font-title);
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.twa-diff .up {
|
||||
color: var(--tgc-od-red);
|
||||
font-family: var(--font-title);
|
||||
}
|
||||
|
||||
.twa-diff .down {
|
||||
color: var(--tgc-od-green);
|
||||
font-family: var(--font-title);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,93 +1,38 @@
|
||||
<template>
|
||||
<div
|
||||
class="tib-box"
|
||||
:style="{
|
||||
width: modelValue.size,
|
||||
height: modelValue.height,
|
||||
cursor: modelValue.clickable ? 'pointer' : 'default',
|
||||
}"
|
||||
>
|
||||
<div
|
||||
class="tib-bg"
|
||||
:style="{
|
||||
width: modelValue.size,
|
||||
height: modelValue.size,
|
||||
}"
|
||||
>
|
||||
<div class="tib-box">
|
||||
<div class="tib-bg">
|
||||
<slot name="bg">
|
||||
<img :src="modelValue.bg" alt="bg" />
|
||||
<img :src="props.modelValue.bg" alt="bg" />
|
||||
</slot>
|
||||
</div>
|
||||
<div
|
||||
class="tib-icon"
|
||||
:style="{
|
||||
width: modelValue.size,
|
||||
height: modelValue.size,
|
||||
}"
|
||||
>
|
||||
<div class="tib-icon">
|
||||
<slot name="icon">
|
||||
<img :src="modelValue.icon" alt="icon" />
|
||||
<img :src="props.modelValue.icon" alt="icon" />
|
||||
</slot>
|
||||
</div>
|
||||
<div
|
||||
class="tib-cover"
|
||||
:style="{
|
||||
width: modelValue.size,
|
||||
height: modelValue.size,
|
||||
}"
|
||||
>
|
||||
<div
|
||||
class="tib-lt"
|
||||
:style="{
|
||||
width: modelValue.ltSize,
|
||||
height: modelValue.ltSize,
|
||||
}"
|
||||
>
|
||||
<img :src="modelValue.lt" alt="lt" />
|
||||
<div class="tib-cover">
|
||||
<div class="tib-lt">
|
||||
<img :src="props.modelValue.lt" alt="lt" />
|
||||
</div>
|
||||
<div
|
||||
v-show="modelValue.rt"
|
||||
class="tib-rt"
|
||||
:style="{
|
||||
width: modelValue.rtSize,
|
||||
height: modelValue.rtSize,
|
||||
}"
|
||||
>
|
||||
{{ modelValue.rt }}
|
||||
<div v-show="props.modelValue.rt" class="tib-rt">
|
||||
{{ props.modelValue.rt }}
|
||||
</div>
|
||||
<div
|
||||
class="tib-inner"
|
||||
:style="{
|
||||
height: `${props.modelValue.innerHeight ?? 0}px`,
|
||||
fontSize: `${props.modelValue.innerHeight ? props.modelValue.innerHeight / 2 : 0}px`,
|
||||
}"
|
||||
>
|
||||
<div class="tib-inner">
|
||||
<slot name="inner-icon">
|
||||
<img
|
||||
v-show="modelValue.innerIcon"
|
||||
:src="modelValue.innerIcon"
|
||||
v-show="props.modelValue.innerIcon"
|
||||
:src="props.modelValue.innerIcon"
|
||||
alt="inner-icon"
|
||||
:style="{
|
||||
width: `${props.modelValue.innerHeight ?? 0}px`,
|
||||
height: `${props.modelValue.innerHeight ?? 0}px`,
|
||||
}"
|
||||
/>
|
||||
</slot>
|
||||
<slot name="inner-text">
|
||||
<span :title="modelValue.innerText">{{ modelValue.innerText }}</span>
|
||||
<span :title="props.modelValue.innerText">{{ props.modelValue.innerText }}</span>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="modelValue.display === 'outer'"
|
||||
class="tib-outer"
|
||||
:style="{
|
||||
height: `${props.modelValue.outerHeight ?? 0}px`,
|
||||
fontSize: `${props.modelValue.outerHeight ? props.modelValue.outerHeight / 2 : 0}px`,
|
||||
}"
|
||||
>
|
||||
<div v-if="props.modelValue.display === 'outer'" class="tib-outer">
|
||||
<slot name="outer-text">
|
||||
<span>{{ modelValue.outerText }}</span>
|
||||
<span>{{ props.modelValue.outerText }}</span>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
@@ -109,6 +54,7 @@ export interface TItemBoxData {
|
||||
innerText: string;
|
||||
outerHeight?: number;
|
||||
outerText?: string;
|
||||
innerBlur?: string;
|
||||
}
|
||||
|
||||
interface TItemBoxProps {
|
||||
@@ -116,10 +62,23 @@ interface TItemBoxProps {
|
||||
}
|
||||
|
||||
const props = defineProps<TItemBoxProps>();
|
||||
const size = props.modelValue.size;
|
||||
const height = props.modelValue.height;
|
||||
const cursor = props.modelValue.clickable ? "pointer" : "default";
|
||||
const sizeLt = props.modelValue.ltSize;
|
||||
const sizeRt = props.modelValue.rtSize;
|
||||
const sizeInner = props.modelValue.innerHeight ?? 0;
|
||||
const fontSizeInner = sizeInner ? `${sizeInner / 2}px` : "0";
|
||||
const sizeOuter = props.modelValue.outerHeight ?? 0;
|
||||
const fontSizeOuter = sizeOuter ? `${sizeOuter / 2}px` : "0";
|
||||
const innerBlur = props.modelValue.innerBlur ?? "0";
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.tib-box {
|
||||
position: relative;
|
||||
width: v-bind(size);
|
||||
height: v-bind(height);
|
||||
cursor: v-bind(cursor);
|
||||
}
|
||||
|
||||
.tib-bg {
|
||||
@@ -127,6 +86,8 @@ const props = defineProps<TItemBoxProps>();
|
||||
top: 0;
|
||||
left: 0;
|
||||
overflow: hidden;
|
||||
width: v-bind(size);
|
||||
height: v-bind(size);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
@@ -139,6 +100,8 @@ const props = defineProps<TItemBoxProps>();
|
||||
.tib-icon {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
width: v-bind(size);
|
||||
height: v-bind(size);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
@@ -153,6 +116,8 @@ const props = defineProps<TItemBoxProps>();
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
width: v-bind(size);
|
||||
height: v-bind(size);
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -164,6 +129,8 @@ const props = defineProps<TItemBoxProps>();
|
||||
top: 3%;
|
||||
left: 3%;
|
||||
display: flex;
|
||||
width: v-bind(sizeLt);
|
||||
height: v-bind(sizeLt);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
@@ -179,6 +146,8 @@ const props = defineProps<TItemBoxProps>();
|
||||
top: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
width: v-bind(sizeRt);
|
||||
height: v-bind(sizeRt);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgb(0 0 0 / 40%);
|
||||
@@ -194,16 +163,22 @@ const props = defineProps<TItemBoxProps>();
|
||||
left: 0;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: v-bind(sizeInner);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
-webkit-backdrop-filter: blur(v-bind(innerBlur));
|
||||
backdrop-filter: blur(v-bind(innerBlur));
|
||||
background: rgb(20 20 20 / 40%);
|
||||
border-bottom-left-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
color: var(--tgc-white-1);
|
||||
font-family: var(--font-title);
|
||||
font-size: v-bind(fontSizeInner);
|
||||
}
|
||||
|
||||
.tib-inner img {
|
||||
width: v-bind(sizeInner);
|
||||
height: v-bind(sizeInner);
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
@@ -219,9 +194,11 @@ const props = defineProps<TItemBoxProps>();
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: v-bind(sizeOuter);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--common-text-title);
|
||||
font-size: v-bind(fontSizeOuter);
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -26,20 +26,20 @@
|
||||
<div class="hta-box">
|
||||
<v-window v-model="tab" class="hta-tab-item">
|
||||
<v-window-item value="use">
|
||||
<HtaTabUse v-if="abyssData.use !== null" :data="avatarUse" />
|
||||
<HtaTabUse v-if="abyssData.use !== null" :data="abyssData.use" />
|
||||
</v-window-item>
|
||||
<v-window-item value="up">
|
||||
<HtaTabUp v-if="abyssData.up !== null" :data="avatarUp" />
|
||||
<HtaTabUp v-if="abyssData.up !== null" :data="abyssData.up" />
|
||||
</v-window-item>
|
||||
<v-window-item value="team">
|
||||
<HtaTabTeam v-if="abyssData.team !== null" :data="teamCombination" />
|
||||
<HtaTabTeam v-if="abyssData.team !== null" :data="abyssData.team" />
|
||||
</v-window-item>
|
||||
<v-window-item value="hold">
|
||||
<HtaTabHold v-if="abyssData.hold !== null" :data="avatarHold" />
|
||||
<HtaTabHold v-if="abyssData.hold !== null" :data="abyssData.hold" />
|
||||
</v-window-item>
|
||||
</v-window>
|
||||
</div>
|
||||
<HtaOverlayOverview v-model="showDialog" :data="overview" />
|
||||
<HtaOverlayOverview v-if="overview" v-model="showDialog" :data="overview" />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, watch } from "vue";
|
||||
@@ -112,8 +112,7 @@ onMounted(async () => {
|
||||
});
|
||||
|
||||
function show(): void {
|
||||
if (showDialog.value) showDialog.value = false;
|
||||
showDialog.value = true;
|
||||
showDialog.value = !showDialog.value;
|
||||
}
|
||||
|
||||
async function refreshData(type: AbyssTab): Promise<void> {
|
||||
@@ -200,15 +199,13 @@ async function getData(type: AbyssTab): Promise<AbyssDataItemType<AbyssTab>> {
|
||||
.hta-box {
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
max-height: calc(100vh - 30px);
|
||||
box-sizing: border-box;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 10px var(--common-shadow-4);
|
||||
}
|
||||
|
||||
.hta-tab-item {
|
||||
width: 100%;
|
||||
height: calc(100% - 60px);
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user