♻️ itemBox 组件重构,更加自由

This commit is contained in:
BTMuli
2023-06-02 17:43:10 +08:00
parent bb2fe8cf46
commit 50b1f16f7f
7 changed files with 161 additions and 144 deletions

View File

@@ -1,30 +1,32 @@
<template> <template>
<TItemBox :data="character as Record<string,string|number>" size="70px" display="inner" model-value="abyss-detail" /> <TItemBox :model-value="box" />
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
// vue // vue
import { onMounted, ref } from "vue"; import { onMounted, ref } from "vue";
import TItemBox from "../main/t-itembox.vue"; import TItemBox, { TItemBoxData } from "../main/t-itembox.vue";
// utils // utils
import TGSqlite from "../../plugins/Sqlite"; import TGSqlite from "../../plugins/Sqlite";
interface TibAbyssDetailProps { interface TibAbyssDetailProps {
modelValue: TGApp.Sqlite.Abyss.CharacterInfo modelValue: TGApp.Sqlite.Abyss.CharacterInfo;
}
export interface TibAbyssDetailAvatar extends TGApp.Sqlite.Character.AppData {
value: number,
} }
const props = defineProps<TibAbyssDetailProps>(); const props = defineProps<TibAbyssDetailProps>();
const box = ref({} as TItemBoxData);
const character = ref({} as TibAbyssDetailAvatar);
onMounted(async () => { onMounted(async () => {
const res = await TGSqlite.getAppCharacter(props.modelValue.id); const res = await TGSqlite.getAppCharacter(props.modelValue.id);
character.value = { box.value = {
...res, height: "70px",
value: props.modelValue.level, ltSize: "25px",
} as TibAbyssDetailAvatar; bg: `/icon/bg/${props.modelValue.star}-Star.webp`,
icon: `/WIKI/character/icon/${props.modelValue.id}.webp`,
lt: `/icon/element/${res.element}元素.webp`,
innerText: `Lv.${props.modelValue.level}`,
innerHeight: 20,
display: "inner",
size: "70px",
};
}); });
</script> </script>

View File

@@ -1,10 +1,10 @@
<template> <template>
<TItemBox :data="character as Record<string,string|number>" size="80px" model-value="abyss-overview" display="inner" /> <TItemBox :model-value="box" />
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
// vue // vue
import { onMounted, ref } from "vue"; import { onMounted, ref } from "vue";
import TItemBox from "../main/t-itembox.vue"; import TItemBox, { TItemBoxData } from "../main/t-itembox.vue";
// utils // utils
import TGSqlite from "../../plugins/Sqlite"; import TGSqlite from "../../plugins/Sqlite";
@@ -12,19 +12,21 @@ interface TibAbyssOverviewProps {
modelValue: TGApp.Sqlite.Abyss.Character; modelValue: TGApp.Sqlite.Abyss.Character;
} }
export interface TibAbyssOverviewAvatar extends TGApp.Sqlite.Character.AppData {
value: number,
}
const props = defineProps<TibAbyssOverviewProps>(); const props = defineProps<TibAbyssOverviewProps>();
const box = ref({} as TItemBoxData);
const character = ref({} as TibAbyssOverviewAvatar);
onMounted(async () => { onMounted(async () => {
const res = await TGSqlite.getAppCharacter(props.modelValue.id); const res = await TGSqlite.getAppCharacter(props.modelValue.id);
character.value = { box.value = {
...res, height: "80px",
value: props.modelValue.value, ltSize: "30px",
} as TibAbyssOverviewAvatar; bg: `/icon/bg/${props.modelValue.star}-Star.webp`,
icon: `/WIKI/character/icon/${props.modelValue.id}.webp`,
lt: `/icon/element/${res.element}元素.webp`,
innerText: props.modelValue.value.toString(),
display: "inner",
size: "80px",
innerHeight: 20,
};
}); });
</script> </script>

View File

@@ -1,13 +1,28 @@
<template> <template>
<TItemBox :data="props.modelValue as Record<string,string|number>" :size="props.size" model-value="calendar-avatar" display="inner" /> <TItemBox :model-value="box" />
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import TItemBox from "../main/t-itembox.vue"; // vue
import { computed } from "vue";
import TItemBox, { TItemBoxData } from "../main/t-itembox.vue";
interface TibCalendarAvatarProps { interface TibCalendarAvatarProps {
size: string,
modelValue: TGApp.App.Calendar.Item modelValue: TGApp.App.Calendar.Item
} }
const props = defineProps<TibCalendarAvatarProps>(); const props = defineProps<TibCalendarAvatarProps>();
const box = computed(() => {
return {
bg: props.modelValue.bg,
icon: props.modelValue.icon,
size: "100px",
height: "100px",
display: "inner",
lt: props.modelValue.elementIcon,
ltSize: "30px",
innerHeight: 25,
innerIcon: props.modelValue.weaponIcon,
innerText: props.modelValue.name,
} as TItemBoxData;
});
</script> </script>

View File

@@ -1,13 +1,27 @@
<template> <template>
<TItemBox :data="props.modelValue as Record<string,string|number>" :size="props.size" model-value="calendar-weapon" display="inner" /> <TItemBox :model-value="box" />
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import TItemBox from "../main/t-itembox.vue"; // vue
import { computed } from "vue";
import TItemBox, { TItemBoxData } from "../main/t-itembox.vue";
interface TibCalendarWeaponProps { interface TibCalendarWeaponProps {
size: string, modelValue: TGApp.App.Calendar.Item;
modelValue: TGApp.App.Calendar.Item
} }
const props = defineProps<TibCalendarWeaponProps>(); const props = defineProps<TibCalendarWeaponProps>();
const box = computed(() => {
return {
bg: props.modelValue.bg,
icon: props.modelValue.icon,
size: "100px",
height: "100px",
display: "inner",
lt: props.modelValue.weaponIcon,
ltSize: "30px",
innerHeight: 25,
innerText: props.modelValue.name,
} as TItemBoxData;
});
</script> </script>

View File

@@ -1,13 +1,28 @@
<template> <template>
<TItemBox :data="props.modelValue as Record<string,string|number>" :size="props.size" model-value="wiki-avatar" display="inner" /> <TItemBox :model-value="box" />
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import TItemBox from "../main/t-itembox.vue"; // vue
import { computed } from "vue";
import TItemBox, { TItemBoxData } from "../main/t-itembox.vue";
interface TibCalendarAvatarProps { interface TibCalendarAvatarProps {
size: string, modelValue: TGApp.App.Character.WikiBriefInfo;
modelValue: TGApp.App.Character.WikiBriefInfo
} }
const props = defineProps<TibCalendarAvatarProps>(); const props = defineProps<TibCalendarAvatarProps>();
const box = computed(() => {
return {
bg: `/icon/bg/${props.modelValue.star}-Star.webp`,
icon: `/WIKI/character/icon/${props.modelValue.id}.webp`,
size: "128px",
height: "128px",
display: "inner",
lt: `/icon/element/${props.modelValue.element}元素.webp`,
ltSize: "40px",
innerHeight: 30,
innerIcon: `/icon/weapon/${props.modelValue.weapon}.webp`,
innerText: props.modelValue.name,
} as TItemBoxData;
});
</script> </script>

View File

@@ -1,13 +1,27 @@
<template> <template>
<TItemBox :data="props.modelValue as Record<string,string|number>" :size="props.size" model-value="wiki-weapon" display="inner" /> <TItemBox :model-value="box" />
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import TItemBox from "../main/t-itembox.vue"; // vue
import { computed } from "vue";
import TItemBox, { TItemBoxData } from "../main/t-itembox.vue";
interface TibCalendarWeaponProps { interface TibCalendarWeaponProps {
size: string,
modelValue: TGApp.App.Weapon.WikiBriefInfo modelValue: TGApp.App.Weapon.WikiBriefInfo
} }
const props = defineProps<TibCalendarWeaponProps>(); const props = defineProps<TibCalendarWeaponProps>();
const box = computed(() => {
return {
bg: props.modelValue.bg,
icon: props.modelValue.icon,
size: "128px",
height: "128px",
display: "inner",
lt: props.modelValue.weaponIcon,
ltSize: "40px",
innerText: props.modelValue.name,
innerHeight: 30,
} as TItemBoxData;
});
</script> </script>

View File

@@ -2,133 +2,87 @@
<div class="tib-box"> <div class="tib-box">
<div class="tib-bg"> <div class="tib-bg">
<slot name="bg"> <slot name="bg">
<img :src="card.bg" alt="bg"> <img :src="modelValue.bg" alt="bg">
</slot> </slot>
</div> </div>
<div class="tib-icon"> <div class="tib-icon">
<slot name="icon"> <slot name="icon">
<img :src="card.icon" alt="icon"> <img :src="modelValue.icon" alt="icon">
</slot> </slot>
</div> </div>
<div class="tib-cover"> <div class="tib-cover">
<div class="tib-lt"> <div class="tib-lt">
<img :src="card.lt" alt="lt"> <img :src="modelValue.lt" alt="lt">
</div> </div>
<div v-show="card.rt" class="tib-rt"> <div v-show="modelValue.rt" class="tib-rt">
{{ card.rt }} {{ modelValue.rt }}
</div> </div>
<div v-show="props.display==='inner'" class="tib-inner"> <div v-if="modelValue.display==='inner'" class="tib-inner">
<slot name="inner-icon"> <slot name="inner-icon">
<img v-show="card.innerIcon" :src="card.innerIcon" alt="inner-icon"> <img v-show="modelValue.innerIcon" :src="modelValue.innerIcon" alt="inner-icon">
</slot> </slot>
<slot name="inner-text"> <slot name="inner-text">
<span>{{ card.innerText }}</span> <span>{{ modelValue.innerText }}</span>
</slot> </slot>
</div> </div>
<div v-show="props.display==='outer'" class="tib-outer"> <div v-if="modelValue.display==='outer'" class="tib-outer">
<slot name="outer-icon"> <slot name="outer-icon">
<img v-show="card.outerIcon" :src="card.outerIcon" alt="outer-icon"> <img v-show="modelValue.outerIcon" :src="modelValue.outerIcon" alt="outer-icon">
</slot> </slot>
<slot name="outer-text"> <slot name="outer-text">
<span>{{ card.outerText }}</span> <span>{{ modelValue.outerText }}</span>
</slot> </slot>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
// vue import { computed } from "vue";
import { computed, ComputedRef } from "vue";
// types
import { TibAbyssOverviewAvatar } from "../itembox/tib-abyss-overview.vue";
import { TibAbyssDetailAvatar } from "../itembox/tib-abyss-detail.vue";
interface TItemBoxProps { export interface TItemBoxData {
modelValue: string
data: Record<string, string | number>,
display: "inner" | "outer",
size: string,
}
interface TItemBoxCard {
bg: string, bg: string,
icon: string, icon: string,
size: string,
height: string,
display: "inner" | "outer",
lt: string, lt: string,
ltSize: string,
rt?: string, rt?: string,
rtSize?: string,
innerHeight?: number,
innerIcon?: string, innerIcon?: string,
innerText?: string, innerText?: string,
outerHeight?: number,
outerIcon?: string, outerIcon?: string,
outerText?: string, outerText?: string,
} }
const props = defineProps<TItemBoxProps>(); interface TItemBoxProps {
modelValue: TItemBoxData,
}
const getHeight = computed(() => { const props = withDefaults(defineProps<TItemBoxProps>(), {
return props.display === "inner" ? props.size : `${Number(props.size.slice(0, -2)) + 20}px`; modelValue: {
}); bg: "",
icon: "",
const card: ComputedRef<TItemBoxCard> = computed(() => { lt: "",
let cardData; ltSize: "30px",
switch (props.modelValue) { display: "inner",
case "calendar-avatar": size: "80px",
cardData = props.data as TGApp.App.Calendar.Item; height: "80px",
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;
return {
bg: `/icon/bg/${cardData.star}-Star.webp`,
icon: `/WIKI/character/icon/${cardData.id}.webp`,
lt: `/icon/element/${cardData.element}元素.webp`,
innerIcon: `/icon/weapon/${cardData.weapon}.webp`,
innerText: cardData.name,
} as TItemBoxCard;
case "wiki-weapon":
cardData = props.data as TGApp.App.Weapon.WikiBriefInfo;
return {
bg: cardData.bg,
icon: cardData.icon,
lt: cardData.weaponIcon,
innerText: cardData.name,
} as TItemBoxCard;
case "abyss-overview":
cardData = props.data as TibAbyssOverviewAvatar;
return {
bg: `/icon/bg/${cardData.star}-Star.webp`,
icon: `/WIKI/character/icon/${cardData.id}.webp`,
lt: `/icon/element/${cardData.element}元素.webp`,
innerText: cardData.value,
} as TItemBoxCard;
case "abyss-detail":
cardData = props.data as TibAbyssDetailAvatar;
return {
bg: `/icon/bg/${cardData.star}-Star.webp`,
icon: `/WIKI/character/icon/${cardData.id}.webp`,
lt: `/icon/element/${cardData.element}元素.webp`,
innerText: `Lv.${cardData.value}`,
} as TItemBoxCard;
}
}); });
const getInnerHeight = computed(() => `${props.modelValue.innerHeight}px`);
const getInnerFont = computed(() => `${props.modelValue.innerHeight / 2}px`);
const getOuterHeight = computed(() => `${props.modelValue.outerHeight}px`);
const getOuterFont = computed(() => `${props.modelValue.outerHeight / 2}px`);
</script> </script>
<style lang="css" scoped> <style lang="css" scoped>
.tib-box { .tib-box {
position: relative; position: relative;
width: v-bind(size); width: v-bind(props["modelValue"]["size"]);
height: v-bind(getHeight); height: v-bind(props["modelValue"]["height"]);
cursor: pointer; cursor: pointer;
} }
@@ -136,29 +90,29 @@ const card: ComputedRef<TItemBoxCard> = computed(() => {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: v-bind(props["modelValue"]["size"]);
height: 100%; height: v-bind(props["modelValue"]["size"]);
border-radius: 5px; border-radius: 5px;
overflow: hidden; overflow: hidden;
} }
.tib-bg img { .tib-bg img {
width: v-bind(size); width: 100%;
height: v-bind(size); height: 100%;
object-fit: cover; object-fit: cover;
} }
.tib-icon { .tib-icon {
position: relative; position: relative;
width: 100%; width: v-bind(props["modelValue"]["size"]);
height: 100%; height: v-bind(props["modelValue"]["size"]);
overflow: hidden; overflow: hidden;
border-radius: 5px; border-radius: 5px;
} }
.tib-icon img { .tib-icon img {
width: v-bind(size); width: 100%;
height: v-bind(size); height: 100%;
object-fit: cover; object-fit: cover;
} }
@@ -166,8 +120,8 @@ const card: ComputedRef<TItemBoxCard> = computed(() => {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: v-bind(props["modelValue"]["size"]);
height: 100%; height: v-bind(props["modelValue"]["size"]);
border-radius: 5px; border-radius: 5px;
display: flex; display: flex;
justify-content: center; justify-content: center;
@@ -179,16 +133,17 @@ const card: ComputedRef<TItemBoxCard> = computed(() => {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: 30px; padding: 5px;
height: 30px; width: v-bind(props["modelValue"]["ltSize"]);
height: v-bind(props["modelValue"]["ltSize"]);
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
.tib-lt img { .tib-lt img {
width: 20px; width: 100%;
height: 20px; height: 100%;
object-fit: cover; object-fit: cover;
} }
@@ -197,7 +152,7 @@ const card: ComputedRef<TItemBoxCard> = computed(() => {
bottom: 0; bottom: 0;
left: 0; left: 0;
width: 100%; width: 100%;
height: 20px; height: v-bind(getInnerHeight);
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
@@ -205,14 +160,14 @@ const card: ComputedRef<TItemBoxCard> = computed(() => {
border-bottom-left-radius: 5px; border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px; border-bottom-right-radius: 5px;
color: #fff; color: #fff;
font-size: 8px; font-size: v-bind(getInnerFont);
text-shadow: 0 0 5px #000; text-shadow: 0 0 5px #000;
font-family: Genshin, serif; font-family: Genshin, serif;
} }
.tib-inner img { .tib-inner img {
width: 20px; width: v-bind(getInnerHeight);
height: 20px; height: v-bind(getInnerHeight);
margin-right: 5px; margin-right: 5px;
} }
@@ -222,14 +177,14 @@ const card: ComputedRef<TItemBoxCard> = computed(() => {
border-bottom-left-radius: 5px; border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px; border-bottom-right-radius: 5px;
width: 100%; width: 100%;
height: 20px; height: v-bind(getOuterHeight);
background: rgb(0 0 0/ 20%); background: rgb(0 0 0/ 20%);
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
font-family: Genshin, serif; font-family: Genshin, serif;
color: #fff; color: #fff;
font-size: 8px; font-size: v-bind(getOuterFont);
text-shadow: 0 0 5px #000; text-shadow: 0 0 5px #000;
} }
</style> </style>