♻️ 优化素材日历组件

This commit is contained in:
BTMuli
2023-06-26 17:00:44 +08:00
parent 05df2c0589
commit 0c923060b8
6 changed files with 139 additions and 175 deletions

View File

@@ -1,28 +0,0 @@
<template>
<TItemBox :model-value="box" style="cursor: pointer" />
</template>
<script lang="ts" setup>
// vue
import { computed } from "vue";
import TItemBox, { TItemBoxData } from "../main/t-itembox.vue";
interface TibCalendarAvatarProps {
modelValue: TGApp.App.Calendar.Item;
}
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>

View File

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

View File

@@ -1,27 +0,0 @@
<template>
<TItemBox :model-value="box" style="cursor: pointer" />
</template>
<script lang="ts" setup>
// vue
import { computed } from "vue";
import TItemBox, { TItemBoxData } from "../main/t-itembox.vue";
interface TibCalendarWeaponProps {
modelValue: TGApp.App.Calendar.Item;
}
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>

View File

@@ -12,8 +12,7 @@
:key="text.week" :key="text.week"
class="calendar-title-btn" class="calendar-title-btn"
:style="{ :style="{
boxShadow: text.week === weekNow ? '0 0 5px #FEC90B' : 'none', border: btnNow === text.week ? '2px solid var(--common-color-yellow)' : 'none',
background: text.week === btnNow ? 'rgba(0,0,0,0.8)' : 'rgba(0,0,0,0.3)',
}" }"
@click="getContents(text.week)" @click="getContents(text.week)"
> >
@@ -21,31 +20,24 @@
</v-btn> </v-btn>
</div> </div>
</div> </div>
<div class="calendar-divider" />
<div class="calendar-sub">
<TSubLine>角色突破</TSubLine> <TSubLine>角色突破</TSubLine>
<div class="cards-grid"> <div class="calendar-grid">
<div <div v-for="item in characterCards" :key="item.id" @click="selectAvatar(item)">
v-for="item in characterCards" <TibCalendarItem
:key="item.id" :data="<TGApp.App.Calendar.Item>item"
class="card-box" :model="'avatar'"
@click="selectContent(item, 'character')" :clickable="true"
> />
<TibCalendarAvatar size="100px" :model-value="item" />
</div> </div>
</div> </div>
</div>
<div class="calendar-sub">
<TSubLine>武器突破</TSubLine> <TSubLine>武器突破</TSubLine>
<div class="cards-grid"> <div class="calendar-grid">
<div <div v-for="item in weaponCards" :key="item.id" @click="selectWeapon(item)">
v-for="item in weaponCards" <TibCalendarItem
:key="item.id" :data="<TGApp.App.Calendar.Item>item"
class="card-box" :model="'weapon'"
@click="selectContent(item, 'weapon')" :clickable="true"
> />
<TibCalendarWeapon size="100px" :model-value="item" />
</div>
</div> </div>
</div> </div>
<ToCalendar v-model="showItem" :data-type="selectedType" :data-val="selectedItem" /> <ToCalendar v-model="showItem" :data-type="selectedType" :data-val="selectedItem" />
@@ -56,29 +48,28 @@
import { computed, onMounted, ref } from "vue"; import { computed, onMounted, ref } from "vue";
import TSubLine from "./t-subline.vue"; import TSubLine from "./t-subline.vue";
import ToCalendar from "../overlay/to-calendar.vue"; import ToCalendar from "../overlay/to-calendar.vue";
import TibCalendarAvatar from "../itembox/tib-calendar-avatar.vue"; import TibCalendarItem from "../itembox/tib-calendar-item.vue";
import TibCalendarWeapon from "../itembox/tib-calendar-weapon.vue";
// data // data
import { AppCalendarData } from "../../data"; import { AppCalendarData } from "../../data";
// loading // loading
const loading = ref(true as boolean); const loading = ref<boolean>(true);
// data // data
const calendarData = computed(() => AppCalendarData); const calendarData = computed<TGApp.App.Calendar.Item[]>(() => AppCalendarData);
const weekNow = ref(0 as number); const weekNow = ref<number>(0);
const btnNow = ref(0 as number); const btnNow = ref<number>(0);
const dateNow = ref(new Date().toLocaleDateString()); const dateNow = ref<string>("");
// calendar // calendar
const calendarNow = ref([] as TGApp.App.Calendar.Item[]); const calendarNow = ref<TGApp.App.Calendar.Item[]>([]);
const characterCards = ref([] as TGApp.App.Calendar.Item[]); const characterCards = ref<TGApp.App.Calendar.Item[]>([]);
const weaponCards = ref([] as TGApp.App.Calendar.Item[]); const weaponCards = ref<TGApp.App.Calendar.Item[]>([]);
// calendar item // calendar item
const showItem = ref(false as boolean); const showItem = ref<boolean>(false);
const selectedItem = ref({} as TGApp.App.Calendar.Item); const selectedItem = ref<TGApp.App.Calendar.Item>({} as TGApp.App.Calendar.Item);
const selectedType = ref("character"); const selectedType = ref<"avatar" | "weapon">("avatar");
const btnText = [ const btnText = [
{ {
@@ -110,6 +101,7 @@ const btnText = [
text: "周六", text: "周六",
}, },
]; ];
// expose // expose
defineExpose({ defineExpose({
name: "素材日历", name: "素材日历",
@@ -118,6 +110,13 @@ defineExpose({
onMounted(() => { onMounted(() => {
const dayNow = new Date().getDay() === 0 ? 7 : new Date().getDay(); const dayNow = new Date().getDay() === 0 ? 7 : new Date().getDay();
dateNow.value = new Date()
.toLocaleDateString("zh-CN", {
year: "numeric",
month: "2-digit",
day: "2-digit",
})
.replace(/\//g, "-");
weekNow.value = dayNow; weekNow.value = dayNow;
btnNow.value = dayNow; btnNow.value = dayNow;
calendarNow.value = getCalendar(dayNow); calendarNow.value = getCalendar(dayNow);
@@ -127,17 +126,23 @@ onMounted(() => {
}); });
// 获取当前日历 // 获取当前日历
function getCalendar(day: number) { function getCalendar(day: number): TGApp.App.Calendar.Item[] {
return calendarData.value.filter((item) => item.dropDays.includes(day)); return calendarData.value.filter((item) => item.dropDays.includes(day));
} }
function selectContent(item: TGApp.App.Calendar.Item, type: string) { function selectAvatar(item: TGApp.App.Calendar.Item): void {
selectedItem.value = item; selectedItem.value = item;
selectedType.value = type; selectedType.value = "avatar";
showItem.value = true; showItem.value = true;
} }
function getContents(day: number) { function selectWeapon(item: TGApp.App.Calendar.Item): void {
selectedItem.value = item;
selectedType.value = "weapon";
showItem.value = true;
}
function getContents(day: number): void {
btnNow.value = day; btnNow.value = day;
calendarNow.value = getCalendar(day); calendarNow.value = getCalendar(day);
characterCards.value = calendarNow.value.filter((item) => item.itemType === "character"); characterCards.value = calendarNow.value.filter((item) => item.itemType === "character");
@@ -148,56 +153,45 @@ function getContents(day: number) {
.calendar-box { .calendar-box {
margin-bottom: 10px; margin-bottom: 10px;
padding: 10px; padding: 10px;
background: rgb(255 255 255 / 10%); box-shadow: 0 0 10px var(--common-shadow-4);
box-shadow: 0 0 10px rgb(0 0 0 / 40%);
border-radius: 5px; border-radius: 5px;
} }
.calendar-title { .calendar-title {
height: 45px; color: var(--common-text-title);
font-family: var(--font-title);
font-size: 20px; font-size: 20px;
display: flex; display: flex;
color: rgb(255 255 255 / 80%); align-items: center;
justify-content: start;
column-gap: 2rem;
padding-bottom: 5px;
border-bottom: 2px solid var(--common-shadow-4);
} }
.calendar-title-left { .calendar-title-left {
width: 20%;
height: 45px;
font-family: Genshin, serif;
text-shadow: 0 0 10px rgb(0 0 0 / 80%);
display: flex; display: flex;
align-items: center; align-items: center;
} justify-content: start;
column-gap: 10px;
.calendar-title-left span {
margin-left: 10px;
} }
.calendar-title-right { .calendar-title-right {
width: 80%; display: flex;
font-family: Genshin-Light, serif; align-items: center;
height: 45px; justify-content: start;
column-gap: 15px;
} }
.calendar-title-btn { .calendar-title-btn {
margin-left: 10px; background: var(--common-bg-1);
color: var(--common-bgt-1);
border-radius: 5px; border-radius: 5px;
} }
.calendar-divider { .calendar-grid {
width: 100%;
height: 2px;
border-radius: 2px;
background: rgb(0 0 0 / 40%);
}
.calendar-sub {
margin: 5px;
}
.cards-grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
grid-gap: 8px; grid-gap: 10px;
} }
</style> </style>

View File

@@ -42,6 +42,7 @@ export interface TItemBoxData {
size: string; size: string;
height: string; height: string;
display: "inner" | "outer"; display: "inner" | "outer";
clickable: boolean;
lt: string; lt: string;
ltSize: string; ltSize: string;
rt?: string; rt?: string;
@@ -57,19 +58,9 @@ interface TItemBoxProps {
modelValue: TItemBoxData; modelValue: TItemBoxData;
} }
const props = withDefaults(defineProps<TItemBoxProps>(), { const props = defineProps<TItemBoxProps>();
modelValue: {
bg: "",
icon: "",
lt: "",
ltSize: "30px",
display: "inner",
innerText: "",
size: "80px",
height: "80px",
},
});
const getCursor = computed(() => (props.modelValue.clickable ? "pointer" : "default"));
const getInnerHeight = computed(() => `${props.modelValue.innerHeight}px`); const getInnerHeight = computed(() => `${props.modelValue.innerHeight}px`);
const getInnerFont = computed(() => `${props.modelValue.innerHeight / 2}px`); const getInnerFont = computed(() => `${props.modelValue.innerHeight / 2}px`);
const getOuterHeight = computed(() => `${props.modelValue.outerHeight}px`); const getOuterHeight = computed(() => `${props.modelValue.outerHeight}px`);
@@ -78,16 +69,17 @@ const getOuterFont = computed(() => `${props.modelValue.outerHeight / 2}px`);
<style lang="css" scoped> <style lang="css" scoped>
.tib-box { .tib-box {
position: relative; position: relative;
width: v-bind(props[ "modelValue"][ "size"]); width: v-bind(modelValue[ "size"]);
height: v-bind(props[ "modelValue"][ "height"]); height: v-bind(modelValue[ "height"]);
cursor: v-bind(getCursor);
} }
.tib-bg { .tib-bg {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: v-bind(props[ "modelValue"][ "size"]); width: v-bind(modelValue[ "size"]);
height: v-bind(props[ "modelValue"][ "size"]); height: v-bind(modelValue[ "size"]);
border-radius: 5px; border-radius: 5px;
overflow: hidden; overflow: hidden;
} }
@@ -100,8 +92,8 @@ const getOuterFont = computed(() => `${props.modelValue.outerHeight / 2}px`);
.tib-icon { .tib-icon {
position: relative; position: relative;
width: v-bind(props[ "modelValue"][ "size"]); width: v-bind(modelValue[ "size"]);
height: v-bind(props[ "modelValue"][ "size"]); height: v-bind(modelValue[ "size"]);
overflow: hidden; overflow: hidden;
border-radius: 5px; border-radius: 5px;
} }
@@ -116,8 +108,8 @@ const getOuterFont = computed(() => `${props.modelValue.outerHeight / 2}px`);
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: v-bind(props[ "modelValue"][ "size"]); width: v-bind(modelValue[ "size"]);
height: v-bind(props[ "modelValue"][ "size"]); height: v-bind(modelValue[ "size"]);
border-radius: 5px; border-radius: 5px;
display: flex; display: flex;
justify-content: center; justify-content: center;
@@ -130,8 +122,8 @@ const getOuterFont = computed(() => `${props.modelValue.outerHeight / 2}px`);
top: 0; top: 0;
left: 0; left: 0;
padding: 5px; padding: 5px;
width: v-bind(props[ "modelValue"][ "ltSize"]); width: v-bind(modelValue[ "ltSize"]);
height: v-bind(props[ "modelValue"][ "ltSize"]); height: v-bind(modelValue[ "ltSize"]);
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
@@ -147,8 +139,8 @@ const getOuterFont = computed(() => `${props.modelValue.outerHeight / 2}px`);
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
width: v-bind(props[ "modelValue"][ "rtSize"]); width: v-bind(modelValue[ "rtSize"]);
height: v-bind(props[ "modelValue"][ "rtSize"]); height: v-bind(modelValue[ "rtSize"]);
background: rgb(0 0 0 / 40%); background: rgb(0 0 0 / 40%);
border-top-right-radius: 5px; border-top-right-radius: 5px;
border-bottom-left-radius: 5px; border-bottom-left-radius: 5px;

View File

@@ -3,18 +3,11 @@
<div class="toc-box"> <div class="toc-box">
<div class="box-div"> <div class="box-div">
<div class="toc-top"> <div class="toc-top">
<div class="toc-icon"> <div class="toc-icon" style="cursor: default">
<TibCalendarAvatar <TibCalendarItem
v-if="itemType === 'character'" :model="itemType"
v-model="itemVal" :data="<TGApp.App.Calendar.Item>itemVal"
size="100px" :clickable="false"
style="cursor: default"
/>
<TibCalendarWeapon
v-if="itemType === 'weapon'"
v-model="itemVal"
size="100px"
style="cursor: default"
/> />
</div> </div>
<div class="toc-material-grid"> <div class="toc-material-grid">
@@ -51,37 +44,32 @@
// vue // vue
import { computed, ref } from "vue"; import { computed, ref } from "vue";
import TOverlay from "../main/t-overlay.vue"; import TOverlay from "../main/t-overlay.vue";
import TibCalendarWeapon from "../itembox/tib-calendar-weapon.vue"; import TibCalendarItem from "../itembox/tib-calendar-item.vue";
import TibCalendarAvatar from "../itembox/tib-calendar-avatar.vue";
import TibCalendarMaterial from "../itembox/tib-calendar-material.vue"; import TibCalendarMaterial from "../itembox/tib-calendar-material.vue";
// utils // utils
import { OBC_CONTENT_API } from "../../plugins/Mys/interface/utils"; import { OBC_CONTENT_API } from "../../plugins/Mys/interface/utils";
import { createTGWindow } from "../../utils/TGWindow"; import { createTGWindow } from "../../utils/TGWindow";
interface TOCalendarProps { interface ToCalendarProps {
modelValue: boolean; modelValue: boolean;
dataType: string; dataType: "weapon" | "avatar";
dataVal: TGApp.App.Calendar.Item; dataVal: TGApp.App.Calendar.Item;
} }
interface TOCalendarEmits { interface ToCalendarEmits {
(e: "update:modelValue", value: TGApp.App.Calendar.Item): void; (e: "update:modelValue", value: boolean): void;
(e: "cancel"): void; (e: "cancel"): void;
} }
const emits = defineEmits<TOCalendarEmits>(); const emits = defineEmits<ToCalendarEmits>();
const props = withDefaults(defineProps<TOCalendarProps>(), { const props = defineProps<ToCalendarProps>();
modelValue: false,
dataType: "",
dataVal: {} as TGApp.App.Calendar.Item,
});
const visible = computed({ const visible = computed({
get: () => props.modelValue, get: () => props.modelValue,
set: (value) => emits("update:modelValue", value), set: (value) => emits("update:modelValue", value),
}); });
const itemType = computed(() => props.dataType); const itemType = computed(() => props.dataType);
const itemVal = computed(() => props.dataVal); const itemVal = computed<TGApp.App.Calendar.Item>(() => props.dataVal);
const snackbar = ref(false); const snackbar = ref(false);
const onCancel = () => { const onCancel = () => {