mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-14 09:38:13 +08:00
47
src/components/userCombat/tuc-avatars.vue
Normal file
47
src/components/userCombat/tuc-avatars.vue
Normal file
@@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<div class="tuca-box">
|
||||
<TItembox v-for="(item, idx) in props.modelValue" :key="idx" :model-value="getItemBox(item)" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed } from "vue";
|
||||
|
||||
import { getZhElement } from "../../utils/toolFunc.js";
|
||||
import TItembox, { TItemBoxData } from "../main/t-itembox.vue";
|
||||
|
||||
interface TucAvatarsProps {
|
||||
modelValue: TGApp.Game.Combat.Avatar[];
|
||||
}
|
||||
|
||||
const props = defineProps<TucAvatarsProps>();
|
||||
const columnCnt = computed<number>(() => {
|
||||
if (props.modelValue.length % 2 === 1) return (props.modelValue.length + 1) / 2;
|
||||
return props.modelValue.length / 2;
|
||||
});
|
||||
|
||||
function getItemBox(item: TGApp.Game.Combat.Avatar): TItemBoxData {
|
||||
return {
|
||||
bg: `/icon/bg/${item.rarity === 105 ? 5 : item.rarity}-BGC.webp`,
|
||||
clickable: false,
|
||||
display: "inner",
|
||||
height: "80px",
|
||||
icon: `/WIKI/character/${item.avatar_id}.webp`,
|
||||
innerHeight: item.avatar_type !== 1 ? 20 : 0,
|
||||
innerText: item.avatar_type === 2 ? "试用角色" : item.avatar_type === 3 ? "助演角色" : "",
|
||||
lt: `/icon/element/${getZhElement(item.element)}元素.webp`,
|
||||
ltSize: "20px",
|
||||
innerBlur: "5px",
|
||||
rt: "",
|
||||
rtSize: "",
|
||||
size: "80px",
|
||||
};
|
||||
}
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.tuca-box {
|
||||
display: grid;
|
||||
width: 100%;
|
||||
grid-gap: 10px;
|
||||
grid-template-columns: repeat(v-bind(columnCnt), 1fr);
|
||||
}
|
||||
</style>
|
||||
68
src/components/userCombat/tuc-buffs.vue
Normal file
68
src/components/userCombat/tuc-buffs.vue
Normal file
@@ -0,0 +1,68 @@
|
||||
<template>
|
||||
<div class="tuc-buff-box">
|
||||
<div class="tuc-buff-item">
|
||||
<img alt="total" src="/source/UI/combatCrown.webp" />
|
||||
<span>{{ props.modelValue.summary.total_level }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="tuc-buff-item"
|
||||
v-for="(item, idx) in props.modelValue.buffs"
|
||||
:key="idx"
|
||||
:title="item.name"
|
||||
>
|
||||
<img :alt="item.name" :src="item.icon" />
|
||||
<span>{{ item.level }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed } from "vue";
|
||||
|
||||
interface TucBuffProps {
|
||||
modelValue: TGApp.Game.Combat.SplendourBuff;
|
||||
}
|
||||
|
||||
const props = defineProps<TucBuffProps>();
|
||||
const columnCnt = computed<number>(() => {
|
||||
const len = props.modelValue.buffs.length;
|
||||
if ((len + 1) % 2 === 1) return len / 2 + 1;
|
||||
return (len + 1) / 2;
|
||||
});
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.tuc-buff-box {
|
||||
display: grid;
|
||||
width: 100%;
|
||||
grid-gap: 5px;
|
||||
grid-template-columns: repeat(v-bind(columnCnt), 1fr);
|
||||
}
|
||||
|
||||
.tuc-buff-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
span {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding: 0 5px;
|
||||
background: var(--common-shadow-2);
|
||||
border-bottom-right-radius: 5px;
|
||||
border-top-left-radius: 5px;
|
||||
color: var(--tgc-white-2);
|
||||
font-family: var(--font-title);
|
||||
font-size: 14px;
|
||||
text-shadow: 0 0 5px rgb(0 0 0 / 20%);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
50
src/components/userCombat/tuc-cards.vue
Normal file
50
src/components/userCombat/tuc-cards.vue
Normal file
@@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<div class="tuc-cards-box">
|
||||
<div
|
||||
class="tuc-cards-item"
|
||||
v-for="(card, idx) in props.modelValue"
|
||||
:key="idx"
|
||||
:title="card.name"
|
||||
>
|
||||
<img :src="card.icon" :alt="card.name" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
interface TucCardsProps {
|
||||
modelValue: TGApp.Game.Combat.Card[];
|
||||
}
|
||||
|
||||
const props = defineProps<TucCardsProps>();
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.tuc-cards-box {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
justify-content: flex-start;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.tuc-cards-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 50px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
aspect-ratio: 1;
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
filter: invert(1);
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
|
||||
.dark .tuc-cards-item {
|
||||
img {
|
||||
filter: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
88
src/components/userCombat/tuc-fight.vue
Normal file
88
src/components/userCombat/tuc-fight.vue
Normal file
@@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<div class="tucfi-box">
|
||||
<div class="tucfi-label">
|
||||
<slot name="label">{{ props.label }}</slot>
|
||||
</div>
|
||||
<div v-if="!Array.isArray(props.data)" class="tucfi-data">
|
||||
<TItembox :model-value="getBox()" />
|
||||
</div>
|
||||
<div class="tucfi-icons" v-else>
|
||||
<div v-for="(item, idx) in props.data" :key="idx" class="tucfi-icon">
|
||||
<TItembox :model-value="getBox2(item)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TItembox, { TItemBoxData } from "../main/t-itembox.vue";
|
||||
|
||||
interface TucFightProps {
|
||||
label: string;
|
||||
data: TGApp.Game.Combat.AvatarMini | TGApp.Game.Combat.AvatarMini[];
|
||||
}
|
||||
|
||||
const props = defineProps<TucFightProps>();
|
||||
|
||||
function getBox(): TItemBoxData {
|
||||
const role = <TGApp.Game.Combat.AvatarMini>props.data;
|
||||
return {
|
||||
bg: `/icon/bg/${role.rarity === 105 ? 5 : role.rarity}-BGC.webp`,
|
||||
clickable: false,
|
||||
display: "inner",
|
||||
height: "60px",
|
||||
icon: `/WIKI/character/${role.avatar_id}.webp`,
|
||||
innerText: role.value,
|
||||
innerHeight: 20,
|
||||
innerBlur: "5px",
|
||||
lt: "",
|
||||
ltSize: "0",
|
||||
size: "60px",
|
||||
};
|
||||
}
|
||||
|
||||
function getBox2(item: TGApp.Game.Combat.AvatarMini): TItemBoxData {
|
||||
return {
|
||||
bg: `/icon/bg/${item.rarity === 105 ? 5 : item.rarity}-BGC.webp`,
|
||||
clickable: false,
|
||||
display: "inner",
|
||||
height: "60px",
|
||||
icon: `/WIKI/character/${item.avatar_id}.webp`,
|
||||
innerText: "",
|
||||
lt: "",
|
||||
ltSize: "0",
|
||||
size: "60px",
|
||||
};
|
||||
}
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.tucfi-box {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
background: var(--box-bg-1);
|
||||
}
|
||||
|
||||
.tucfi-label {
|
||||
color: var(--box-text-4);
|
||||
font-family: var(--font-title);
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.tucfi-data {
|
||||
color: var(--tgc-yellow-1);
|
||||
font-family: var(--font-text);
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.tucfi-icons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
column-gap: 10px;
|
||||
}
|
||||
</style>
|
||||
55
src/components/userCombat/tuc-overview.vue
Normal file
55
src/components/userCombat/tuc-overview.vue
Normal file
@@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<div class="tuco-box">
|
||||
<TucTile title="最佳记录" :val="props.data.max_round_id" />
|
||||
<TucTile :title="`获得星章-${props.data.medal_num}`" :val="props.data.get_medal_round_list" />
|
||||
<TucTile :title="getTitle()" :val="`第${props.data.max_round_id}幕`" />
|
||||
<TucTile title="消耗幻剧之花" :val="props.data.coin_num" />
|
||||
<TucFight label="最快完成演出" :data="props.fights.shortest_avatar_list" />
|
||||
<TucTile title="总耗时" :val="getTime()" />
|
||||
<!-- <TucTile title="助演角色支援" :val="`${props.data.rent_cnt}次`" />-->
|
||||
<!-- <TucTile title="场外声援" :val="`${props.data.avatar_bonus_num}次`" />-->
|
||||
<TucFight label="击败最多敌人" :data="props.fights.max_defeat_avatar" />
|
||||
<TucFight label="最高伤害输出" :data="props.fights.max_damage_avatar" />
|
||||
<TucFight label="最高承受伤害" :data="props.fights.max_take_damage_avatar" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TucFight from "./tuc-fight.vue";
|
||||
import TucTile from "./tuc-tile.vue";
|
||||
|
||||
interface TucOverviewProps {
|
||||
data: TGApp.Game.Combat.Stat;
|
||||
fights: TGApp.Game.Combat.FightStatisic;
|
||||
}
|
||||
|
||||
const props = defineProps<TucOverviewProps>();
|
||||
|
||||
function getTitle(): string {
|
||||
switch (props.data.difficulty_id) {
|
||||
case 1:
|
||||
return "轻简模式";
|
||||
case 2:
|
||||
return "普通模式";
|
||||
case 3:
|
||||
return "困难模式";
|
||||
case 4:
|
||||
return "卓越模式";
|
||||
default:
|
||||
return `未知模式${props.data.difficulty_id}`;
|
||||
}
|
||||
}
|
||||
|
||||
function getTime(): string {
|
||||
const sec = props.fights.total_use_time % 60;
|
||||
const min = (props.fights.total_use_time - sec) / 60;
|
||||
return `${min}分${sec}秒`;
|
||||
}
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.tuco-box {
|
||||
display: grid;
|
||||
width: 100%;
|
||||
grid-gap: 10px;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
</style>
|
||||
86
src/components/userCombat/tuc-round.vue
Normal file
86
src/components/userCombat/tuc-round.vue
Normal file
@@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<div class="tucr-box">
|
||||
<div class="tucr-title">
|
||||
<img :src="`/icon/star/combat${props.modelValue.is_get_medal ? 1 : 0}.webp`" alt="combat" />
|
||||
<span class="main">第{{ props.modelValue.round_id }}幕</span>
|
||||
<span class="sub">{{ timestampToDate(Number(props.modelValue.finish_time) * 1000) }}</span>
|
||||
</div>
|
||||
<div class="tucr-content">
|
||||
<TucSub title="出演角色" class="main">
|
||||
<TucAvatars :model-value="props.modelValue.avatars" />
|
||||
</TucSub>
|
||||
<TucSub title="辉彩祝福" class="main">
|
||||
<TucBuffs :model-value="props.modelValue.splendour_buff" />
|
||||
</TucSub>
|
||||
<TucSub :title="`神秘收获(${props.modelValue.choice_cards.length})`" class="sub">
|
||||
<TucCards :model-value="props.modelValue.choice_cards" />
|
||||
</TucSub>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { timestampToDate } from "../../utils/toolFunc.js";
|
||||
|
||||
import TucAvatars from "./tuc-avatars.vue";
|
||||
import TucBuffs from "./tuc-buffs.vue";
|
||||
import TucCards from "./tuc-cards.vue";
|
||||
import TucSub from "./tuc-sub.vue";
|
||||
|
||||
interface TucRoundProps {
|
||||
modelValue: TGApp.Game.Combat.RoundData;
|
||||
}
|
||||
|
||||
const props = defineProps<TucRoundProps>();
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.tucr-box {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: fit-content;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
background: var(--box-bg-1);
|
||||
row-gap: 5px;
|
||||
}
|
||||
|
||||
.tucr-title {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
margin-right: auto;
|
||||
column-gap: 5px;
|
||||
|
||||
img {
|
||||
width: 30px;
|
||||
aspect-ratio: 1;
|
||||
}
|
||||
|
||||
.main {
|
||||
color: var(--common-text-title);
|
||||
font-family: var(--font-title);
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.sub {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
.tucr-content {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: flex-start;
|
||||
justify-content: flex-start;
|
||||
column-gap: 10px;
|
||||
|
||||
.main {
|
||||
width: 180px;
|
||||
}
|
||||
|
||||
.sub {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
32
src/components/userCombat/tuc-sub.vue
Normal file
32
src/components/userCombat/tuc-sub.vue
Normal file
@@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<div class="tuc-sub-box">
|
||||
<div class="tuc-sub-title">{{ props.title }}</div>
|
||||
<slot name="default" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
interface TucSubProps {
|
||||
title: string;
|
||||
}
|
||||
|
||||
const props = defineProps<TucSubProps>();
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.tuc-sub-box {
|
||||
position: relative;
|
||||
display: flex;
|
||||
height: 200px;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
background: var(--box-bg-2);
|
||||
}
|
||||
|
||||
.tuc-sub-title {
|
||||
margin-right: auto;
|
||||
color: var(--box-text-2);
|
||||
font-family: var(--font-title);
|
||||
}
|
||||
</style>
|
||||
62
src/components/userCombat/tuc-tile.vue
Normal file
62
src/components/userCombat/tuc-tile.vue
Normal file
@@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<div class="tuct-box">
|
||||
<div class="tuct-title">
|
||||
<slot name="title">{{ props.title }}</slot>
|
||||
</div>
|
||||
<div class="tuct-text" v-if="!Array.isArray(props.val)">
|
||||
<slot name="text">{{ props.val }}</slot>
|
||||
</div>
|
||||
<div class="tuct-icons" v-else>
|
||||
<img
|
||||
v-for="(val, idx) in props.val"
|
||||
:key="idx"
|
||||
:src="`/icon/star/combat${val}.webp`"
|
||||
:alt="`${val}`"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
interface TucTileProps {
|
||||
title: string;
|
||||
val: string | number | number[];
|
||||
}
|
||||
|
||||
const props = defineProps<TucTileProps>();
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.tuct-box {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
background: var(--box-bg-1);
|
||||
}
|
||||
|
||||
.tuct-title {
|
||||
color: var(--box-text-4);
|
||||
font-family: var(--font-title);
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.tuct-text {
|
||||
color: var(--tgc-yellow-1);
|
||||
font-family: var(--font-text);
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.tuct-icons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
height: 30px;
|
||||
aspect-ratio: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user