新建 item-box 组件

This commit is contained in:
BTMuli
2023-06-01 19:33:04 +08:00
parent 2b768bbf88
commit ab6a41b09b
4 changed files with 218 additions and 4 deletions

View File

@@ -0,0 +1,13 @@
<template>
<TItemBox :data="props.modelValue as Record<string,string|number>" :size="props.size" model-value="calendar-avatar" display="inner" />
</template>
<script lang="ts" setup>
import TItemBox from "../main/t-itembox.vue";
interface TibCalendarAvatarProps {
size: string,
modelValue: TGApp.App.Calendar.Item
}
const props = defineProps<TibCalendarAvatarProps>();
</script>

View File

@@ -0,0 +1,13 @@
<template>
<TItemBox :data="props.modelValue as Record<string,string|number>" :size="props.size" model-value="calendar-weapon" display="inner" />
</template>
<script lang="ts" setup>
import TItemBox from "../main/t-itembox.vue";
interface TibCalendarWeaponProps {
size: string,
modelValue: TGApp.App.Calendar.Item
}
const props = defineProps<TibCalendarWeaponProps>();
</script>

View File

@@ -36,7 +36,7 @@
class="card-box"
@click="selectContent(item, 'character')"
>
<TMiniAvatar size="100px" :model-value="item" />
<TibCalendarAvatar size="100px" :model-value="item" />
</div>
</div>
</div>
@@ -52,7 +52,7 @@
class="card-box"
@click="selectContent(item, 'weapon')"
>
<TMiniWeapon size="100px" :model-value="item" />
<TibCalendarWeapon size="100px" :model-value="item" />
</div>
</div>
</div>
@@ -63,8 +63,8 @@
// vue
import { computed, onMounted, ref } from "vue";
import ToCalendar from "../overlay/to-calendar.vue";
import TMiniAvatar from "../mini/t-mini-avatar.vue";
import TMiniWeapon from "../mini/t-mini-weapon.vue";
import TibCalendarAvatar from "../itembox/tib-calendar-avatar.vue";
import TibCalendarWeapon from "../itembox/tib-calendar-weapon.vue";
// data
import { AppCalendarData } from "../../data";

View File

@@ -0,0 +1,188 @@
<template>
<div class="tib-box">
<div class="tib-bg">
<slot name="bg">
<img :src="card.bg" alt="bg">
</slot>
</div>
<div class="tib-icon">
<slot name="icon">
<img :src="card.icon" alt="icon">
</slot>
</div>
<div class="tib-cover">
<div class="tib-lt">
<img :src="card.lt" alt="lt">
</div>
<div v-show="card.rt" class="tib-rt">
{{ card.rt }}
</div>
<div v-show="props.display==='inner'" class="tib-inner">
<slot name="inner-icon">
<img v-show="card.innerIcon" :src="card.innerIcon" alt="inner-icon">
</slot>
<slot name="inner-text">
<span>{{ card.innerText }}</span>
</slot>
</div>
<div v-show="props.display==='outer'" class="tib-outer">
<slot name="outer-icon">
<img v-show="card.outerIcon" :src="card.outerIcon" alt="outer-icon">
</slot>
<slot name="outer-text">
<span>{{ card.outerText }}</span>
</slot>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
// vue
import { computed, ComputedRef } from "vue";
interface TItemBoxProps {
modelValue: string
data: Record<string, string | number>,
display: "inner" | "outer",
size: string,
}
interface TItemBoxCard {
bg: string,
icon: string,
lt: string,
rt?: string,
innerIcon?: string,
innerText?: string,
outerIcon?: string,
outerText?: string,
}
const props = defineProps<TItemBoxProps>();
const getSize = computed(() => {
return props.size === "100px" ? "30px" : "40px";
});
const getHeight = computed(() => {
return props.display === "inner" ? props.size : `${props.size.slice(0, -2) + 20}px`;
});
const card: ComputedRef<TItemBoxCard> = computed(() => {
let cardData;
switch (props.modelValue) {
case "calendar-avatar":
cardData = props.data as TGApp.App.Calendar.Item;
return {
bg: cardData.bg,
icon: cardData.icon,
lt: cardData.elementIcon,
innerIcon: cardData.weaponIcon,
innerText: cardData.name,
} as TItemBoxCard;
case "calendar-weapon":
cardData = props.data as TGApp.App.Calendar.Item;
return {
bg: cardData.bg,
icon: cardData.icon,
lt: cardData.weaponIcon,
innerText: cardData.name,
} as TItemBoxCard;
case "wiki-avatar":
cardData = props.data as TGApp.App.Character.WikiBriefInfo;
}
});
</script>
<style lang="css" scoped>
.tib-box {
position: relative;
width: v-bind(size);
height: v-bind(getHeight);
cursor: pointer;
}
.tib-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 5px;
overflow: hidden;
}
.tib-bg img {
width: 100%;
height: 100%;
object-fit: cover;
}
.tib-icon {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
border-radius: 5px;
}
.tib-icon img {
width: 100%;
height: 100%;
object-fit: cover;
}
.tib-cover {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 5px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.tib-lt {
position: absolute;
top: 0;
left: 0;
width: v-bind(getSize);
height: v-bind(getSize);
display: flex;
justify-content: center;
align-items: center;
}
.tib-lt img {
width: calc(v-bind(getSize) - 10px);
height: calc(v-bind(getSize) - 10px);
object-fit: cover;
}
.tib-inner {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: v-bind(getSize);
display: flex;
justify-content: center;
align-items: center;
background: rgb(20 20 20 / 50%);
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
color: #fff;
font-size: calc(v-bind(getSize) / 3);
text-shadow: 0 0 5px #000;
font-family: Genshin, serif;
}
.tib-inner img {
width: calc(v-bind(getSize) / 1.5);
height: calc(v-bind(getSize) / 1.5);
margin-right: 5px;
}
</style>