mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-14 09:38:13 +08:00
♻️ 优化素材日历组件
This commit is contained in:
@@ -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>
|
||||
45
src/components/itembox/tib-calendar-item.vue
Normal file
45
src/components/itembox/tib-calendar-item.vue
Normal 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>
|
||||
@@ -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>
|
||||
@@ -12,8 +12,7 @@
|
||||
:key="text.week"
|
||||
class="calendar-title-btn"
|
||||
:style="{
|
||||
boxShadow: text.week === weekNow ? '0 0 5px #FEC90B' : 'none',
|
||||
background: text.week === btnNow ? 'rgba(0,0,0,0.8)' : 'rgba(0,0,0,0.3)',
|
||||
border: btnNow === text.week ? '2px solid var(--common-color-yellow)' : 'none',
|
||||
}"
|
||||
@click="getContents(text.week)"
|
||||
>
|
||||
@@ -21,31 +20,24 @@
|
||||
</v-btn>
|
||||
</div>
|
||||
</div>
|
||||
<div class="calendar-divider" />
|
||||
<div class="calendar-sub">
|
||||
<TSubLine>角色突破</TSubLine>
|
||||
<div class="cards-grid">
|
||||
<div
|
||||
v-for="item in characterCards"
|
||||
:key="item.id"
|
||||
class="card-box"
|
||||
@click="selectContent(item, 'character')"
|
||||
>
|
||||
<TibCalendarAvatar size="100px" :model-value="item" />
|
||||
</div>
|
||||
<TSubLine>角色突破</TSubLine>
|
||||
<div class="calendar-grid">
|
||||
<div v-for="item in characterCards" :key="item.id" @click="selectAvatar(item)">
|
||||
<TibCalendarItem
|
||||
:data="<TGApp.App.Calendar.Item>item"
|
||||
:model="'avatar'"
|
||||
:clickable="true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="calendar-sub">
|
||||
<TSubLine>武器突破</TSubLine>
|
||||
<div class="cards-grid">
|
||||
<div
|
||||
v-for="item in weaponCards"
|
||||
:key="item.id"
|
||||
class="card-box"
|
||||
@click="selectContent(item, 'weapon')"
|
||||
>
|
||||
<TibCalendarWeapon size="100px" :model-value="item" />
|
||||
</div>
|
||||
<TSubLine>武器突破</TSubLine>
|
||||
<div class="calendar-grid">
|
||||
<div v-for="item in weaponCards" :key="item.id" @click="selectWeapon(item)">
|
||||
<TibCalendarItem
|
||||
:data="<TGApp.App.Calendar.Item>item"
|
||||
:model="'weapon'"
|
||||
:clickable="true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<ToCalendar v-model="showItem" :data-type="selectedType" :data-val="selectedItem" />
|
||||
@@ -56,29 +48,28 @@
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
import TSubLine from "./t-subline.vue";
|
||||
import ToCalendar from "../overlay/to-calendar.vue";
|
||||
import TibCalendarAvatar from "../itembox/tib-calendar-avatar.vue";
|
||||
import TibCalendarWeapon from "../itembox/tib-calendar-weapon.vue";
|
||||
import TibCalendarItem from "../itembox/tib-calendar-item.vue";
|
||||
// data
|
||||
import { AppCalendarData } from "../../data";
|
||||
|
||||
// loading
|
||||
const loading = ref(true as boolean);
|
||||
const loading = ref<boolean>(true);
|
||||
|
||||
// data
|
||||
const calendarData = computed(() => AppCalendarData);
|
||||
const weekNow = ref(0 as number);
|
||||
const btnNow = ref(0 as number);
|
||||
const dateNow = ref(new Date().toLocaleDateString());
|
||||
const calendarData = computed<TGApp.App.Calendar.Item[]>(() => AppCalendarData);
|
||||
const weekNow = ref<number>(0);
|
||||
const btnNow = ref<number>(0);
|
||||
const dateNow = ref<string>("");
|
||||
|
||||
// calendar
|
||||
const calendarNow = ref([] as TGApp.App.Calendar.Item[]);
|
||||
const characterCards = ref([] as TGApp.App.Calendar.Item[]);
|
||||
const weaponCards = ref([] as TGApp.App.Calendar.Item[]);
|
||||
const calendarNow = ref<TGApp.App.Calendar.Item[]>([]);
|
||||
const characterCards = ref<TGApp.App.Calendar.Item[]>([]);
|
||||
const weaponCards = ref<TGApp.App.Calendar.Item[]>([]);
|
||||
|
||||
// calendar item
|
||||
const showItem = ref(false as boolean);
|
||||
const selectedItem = ref({} as TGApp.App.Calendar.Item);
|
||||
const selectedType = ref("character");
|
||||
const showItem = ref<boolean>(false);
|
||||
const selectedItem = ref<TGApp.App.Calendar.Item>({} as TGApp.App.Calendar.Item);
|
||||
const selectedType = ref<"avatar" | "weapon">("avatar");
|
||||
|
||||
const btnText = [
|
||||
{
|
||||
@@ -110,6 +101,7 @@ const btnText = [
|
||||
text: "周六",
|
||||
},
|
||||
];
|
||||
|
||||
// expose
|
||||
defineExpose({
|
||||
name: "素材日历",
|
||||
@@ -118,6 +110,13 @@ defineExpose({
|
||||
|
||||
onMounted(() => {
|
||||
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;
|
||||
btnNow.value = 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));
|
||||
}
|
||||
|
||||
function selectContent(item: TGApp.App.Calendar.Item, type: string) {
|
||||
function selectAvatar(item: TGApp.App.Calendar.Item): void {
|
||||
selectedItem.value = item;
|
||||
selectedType.value = type;
|
||||
selectedType.value = "avatar";
|
||||
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;
|
||||
calendarNow.value = getCalendar(day);
|
||||
characterCards.value = calendarNow.value.filter((item) => item.itemType === "character");
|
||||
@@ -148,56 +153,45 @@ function getContents(day: number) {
|
||||
.calendar-box {
|
||||
margin-bottom: 10px;
|
||||
padding: 10px;
|
||||
background: rgb(255 255 255 / 10%);
|
||||
box-shadow: 0 0 10px rgb(0 0 0 / 40%);
|
||||
box-shadow: 0 0 10px var(--common-shadow-4);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.calendar-title {
|
||||
height: 45px;
|
||||
color: var(--common-text-title);
|
||||
font-family: var(--font-title);
|
||||
font-size: 20px;
|
||||
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 {
|
||||
width: 20%;
|
||||
height: 45px;
|
||||
font-family: Genshin, serif;
|
||||
text-shadow: 0 0 10px rgb(0 0 0 / 80%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.calendar-title-left span {
|
||||
margin-left: 10px;
|
||||
justify-content: start;
|
||||
column-gap: 10px;
|
||||
}
|
||||
|
||||
.calendar-title-right {
|
||||
width: 80%;
|
||||
font-family: Genshin-Light, serif;
|
||||
height: 45px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
column-gap: 15px;
|
||||
}
|
||||
|
||||
.calendar-title-btn {
|
||||
margin-left: 10px;
|
||||
background: var(--common-bg-1);
|
||||
color: var(--common-bgt-1);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.calendar-divider {
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
border-radius: 2px;
|
||||
background: rgb(0 0 0 / 40%);
|
||||
}
|
||||
|
||||
.calendar-sub {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.cards-grid {
|
||||
.calendar-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
|
||||
grid-gap: 8px;
|
||||
grid-gap: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -42,6 +42,7 @@ export interface TItemBoxData {
|
||||
size: string;
|
||||
height: string;
|
||||
display: "inner" | "outer";
|
||||
clickable: boolean;
|
||||
lt: string;
|
||||
ltSize: string;
|
||||
rt?: string;
|
||||
@@ -57,19 +58,9 @@ interface TItemBoxProps {
|
||||
modelValue: TItemBoxData;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<TItemBoxProps>(), {
|
||||
modelValue: {
|
||||
bg: "",
|
||||
icon: "",
|
||||
lt: "",
|
||||
ltSize: "30px",
|
||||
display: "inner",
|
||||
innerText: "",
|
||||
size: "80px",
|
||||
height: "80px",
|
||||
},
|
||||
});
|
||||
const props = defineProps<TItemBoxProps>();
|
||||
|
||||
const getCursor = computed(() => (props.modelValue.clickable ? "pointer" : "default"));
|
||||
const getInnerHeight = computed(() => `${props.modelValue.innerHeight}px`);
|
||||
const getInnerFont = computed(() => `${props.modelValue.innerHeight / 2}px`);
|
||||
const getOuterHeight = computed(() => `${props.modelValue.outerHeight}px`);
|
||||
@@ -78,16 +69,17 @@ const getOuterFont = computed(() => `${props.modelValue.outerHeight / 2}px`);
|
||||
<style lang="css" scoped>
|
||||
.tib-box {
|
||||
position: relative;
|
||||
width: v-bind(props[ "modelValue"][ "size"]);
|
||||
height: v-bind(props[ "modelValue"][ "height"]);
|
||||
width: v-bind(modelValue[ "size"]);
|
||||
height: v-bind(modelValue[ "height"]);
|
||||
cursor: v-bind(getCursor);
|
||||
}
|
||||
|
||||
.tib-bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: v-bind(props[ "modelValue"][ "size"]);
|
||||
height: v-bind(props[ "modelValue"][ "size"]);
|
||||
width: v-bind(modelValue[ "size"]);
|
||||
height: v-bind(modelValue[ "size"]);
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
}
|
||||
@@ -100,8 +92,8 @@ const getOuterFont = computed(() => `${props.modelValue.outerHeight / 2}px`);
|
||||
|
||||
.tib-icon {
|
||||
position: relative;
|
||||
width: v-bind(props[ "modelValue"][ "size"]);
|
||||
height: v-bind(props[ "modelValue"][ "size"]);
|
||||
width: v-bind(modelValue[ "size"]);
|
||||
height: v-bind(modelValue[ "size"]);
|
||||
overflow: hidden;
|
||||
border-radius: 5px;
|
||||
}
|
||||
@@ -116,8 +108,8 @@ const getOuterFont = computed(() => `${props.modelValue.outerHeight / 2}px`);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: v-bind(props[ "modelValue"][ "size"]);
|
||||
height: v-bind(props[ "modelValue"][ "size"]);
|
||||
width: v-bind(modelValue[ "size"]);
|
||||
height: v-bind(modelValue[ "size"]);
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@@ -130,8 +122,8 @@ const getOuterFont = computed(() => `${props.modelValue.outerHeight / 2}px`);
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 5px;
|
||||
width: v-bind(props[ "modelValue"][ "ltSize"]);
|
||||
height: v-bind(props[ "modelValue"][ "ltSize"]);
|
||||
width: v-bind(modelValue[ "ltSize"]);
|
||||
height: v-bind(modelValue[ "ltSize"]);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@@ -147,8 +139,8 @@ const getOuterFont = computed(() => `${props.modelValue.outerHeight / 2}px`);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: v-bind(props[ "modelValue"][ "rtSize"]);
|
||||
height: v-bind(props[ "modelValue"][ "rtSize"]);
|
||||
width: v-bind(modelValue[ "rtSize"]);
|
||||
height: v-bind(modelValue[ "rtSize"]);
|
||||
background: rgb(0 0 0 / 40%);
|
||||
border-top-right-radius: 5px;
|
||||
border-bottom-left-radius: 5px;
|
||||
|
||||
@@ -3,18 +3,11 @@
|
||||
<div class="toc-box">
|
||||
<div class="box-div">
|
||||
<div class="toc-top">
|
||||
<div class="toc-icon">
|
||||
<TibCalendarAvatar
|
||||
v-if="itemType === 'character'"
|
||||
v-model="itemVal"
|
||||
size="100px"
|
||||
style="cursor: default"
|
||||
/>
|
||||
<TibCalendarWeapon
|
||||
v-if="itemType === 'weapon'"
|
||||
v-model="itemVal"
|
||||
size="100px"
|
||||
style="cursor: default"
|
||||
<div class="toc-icon" style="cursor: default">
|
||||
<TibCalendarItem
|
||||
:model="itemType"
|
||||
:data="<TGApp.App.Calendar.Item>itemVal"
|
||||
:clickable="false"
|
||||
/>
|
||||
</div>
|
||||
<div class="toc-material-grid">
|
||||
@@ -51,37 +44,32 @@
|
||||
// vue
|
||||
import { computed, ref } from "vue";
|
||||
import TOverlay from "../main/t-overlay.vue";
|
||||
import TibCalendarWeapon from "../itembox/tib-calendar-weapon.vue";
|
||||
import TibCalendarAvatar from "../itembox/tib-calendar-avatar.vue";
|
||||
import TibCalendarItem from "../itembox/tib-calendar-item.vue";
|
||||
import TibCalendarMaterial from "../itembox/tib-calendar-material.vue";
|
||||
// utils
|
||||
import { OBC_CONTENT_API } from "../../plugins/Mys/interface/utils";
|
||||
import { createTGWindow } from "../../utils/TGWindow";
|
||||
|
||||
interface TOCalendarProps {
|
||||
interface ToCalendarProps {
|
||||
modelValue: boolean;
|
||||
dataType: string;
|
||||
dataType: "weapon" | "avatar";
|
||||
dataVal: TGApp.App.Calendar.Item;
|
||||
}
|
||||
|
||||
interface TOCalendarEmits {
|
||||
(e: "update:modelValue", value: TGApp.App.Calendar.Item): void;
|
||||
interface ToCalendarEmits {
|
||||
(e: "update:modelValue", value: boolean): void;
|
||||
(e: "cancel"): void;
|
||||
}
|
||||
|
||||
const emits = defineEmits<TOCalendarEmits>();
|
||||
const props = withDefaults(defineProps<TOCalendarProps>(), {
|
||||
modelValue: false,
|
||||
dataType: "",
|
||||
dataVal: {} as TGApp.App.Calendar.Item,
|
||||
});
|
||||
const emits = defineEmits<ToCalendarEmits>();
|
||||
const props = defineProps<ToCalendarProps>();
|
||||
|
||||
const visible = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (value) => emits("update:modelValue", value),
|
||||
});
|
||||
const itemType = computed(() => props.dataType);
|
||||
const itemVal = computed(() => props.dataVal);
|
||||
const itemVal = computed<TGApp.App.Calendar.Item>(() => props.dataVal);
|
||||
const snackbar = ref(false);
|
||||
|
||||
const onCancel = () => {
|
||||
|
||||
Reference in New Issue
Block a user