♻️ 首页组件样式迭代

This commit is contained in:
目棃
2024-03-26 16:38:14 +08:00
parent 6b2ef079ca
commit 6a0749f234
7 changed files with 223 additions and 290 deletions

View File

@@ -1,7 +1,7 @@
/** /**
* @file assets/themes/dark.css * @file assets/themes/dark.css
* @description 主题样式文件-深色主题 * @description 主题样式文件-深色主题
* @since Beta v0.4.1 * @since Beta v0.4.5
*/ */
/* dark mode */ /* dark mode */
@@ -18,6 +18,8 @@ html.dark {
--box-bg-3: #282c34; --box-bg-3: #282c34;
--box-bg-4: #3d424b; --box-bg-4: #3d424b;
--box-bg-blue: var(--tgc-blue-1);
/* box bg transparent */ /* box bg transparent */
--box-bg-t-1: var(--tgc-white-3); --box-bg-t-1: var(--tgc-white-3);

View File

@@ -18,6 +18,8 @@ html.default {
--box-bg-3: #dee4e9; --box-bg-3: #dee4e9;
--box-bg-4: #f5f5f5; --box-bg-4: #f5f5f5;
--box-bg-blue: var(--tgc-blue-2);
/* box bg transparent */ /* box bg transparent */
--box-bg-t-1: var(--tgc-dark-5); --box-bg-t-1: var(--tgc-dark-5);

View File

@@ -1,79 +1,61 @@
<template> <template>
<div class="calendar-box"> <THomecard append>
<div class="calendar-title"> <template #title>今日素材 {{ dateNow }}</template>
<div class="calendar-title-left"> <template #title-append>
<v-icon size="small" style="opacity: 0.8">mdi-calendar-clock</v-icon> <v-switch
<span>今日素材</span> class="tc-switch"
<span>{{ dateNow }}</span> variant="outline"
:label="switchType === 'avatar' ? '角色' : '武器'"
@change="switchType = switchType === 'avatar' ? 'weapon' : 'avatar'"
/>
</template>
<template #default>
<div class="tc-top">
<div class="tc-btns">
<v-btn
v-for="text of btnText"
:key="text.week"
rounded
:style="{
border: text.week === weekNow ? '1px solid var(--common-shadow-4)' : 'none',
backgroundColor: text.week === btnNow ? 'var(--tgc-yellow-1)' : 'var(--tgc-btn-1)',
color: text.week === btnNow ? 'var(--box-text-4)' : 'var(--btn-text)',
}"
@click="getContents(text.week)"
>{{ text.text }}
</v-btn>
</div>
<v-pagination class="tc-page" v-model="page" total-visible="20" :length="length" />
</div> </div>
<div class="calendar-title-mid"> <div class="calendar-grid">
<v-btn <div v-for="item in getGrid()" :key="item.id" @click="selectItem(item)">
v-for="text of btnText" <TibCalendarItem
:key="text.week" :data="<TGApp.App.Calendar.Item>item"
:style="{ :model="switchType"
border: text.week === weekNow ? '1px solid var(--box-text-2)' : 'none', :clickable="true"
borderRadius: '5px', />
backgroundColor: text.week === btnNow ? 'var(--tgc-yellow-1)' : 'inherit', </div>
color: text.week === btnNow ? 'var(--box-text-4)' : 'inherit',
}"
variant="tonal"
@click="getContents(text.week)"
>
{{ text.text }}
</v-btn>
</div> </div>
<div class="calendar-title-right"> </template>
<v-switch </THomecard>
class="calendar-title-switch" <ToCalendar v-model="showItem" :data-type="selectedType" :data-val="selectedItem" />
color="var(--common-shadow-4)"
variant="outline"
:label="switchType === 'avatar' ? '角色' : '武器'"
@change="switchType = switchType === 'avatar' ? 'weapon' : 'avatar'"
/>
<v-btn class="calendar-title-btn" @click="share" data-html2canvas-ignore>
<template #prepend>
<v-icon>mdi-share-variant</v-icon>
</template>
<span>分享</span>
</v-btn>
</div>
</div>
<v-divider class="calendar-divider" />
<div v-show="switchType === 'avatar'" 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 v-show="switchType !== 'avatar'" 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" />
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, onMounted, ref } from "vue"; import { computed, onMounted, ref } from "vue";
import THomecard from "./t-homecard.vue";
import { AppCalendarData } from "../../data"; import { AppCalendarData } from "../../data";
import { generateShareImg } from "../../utils/TGShare";
import TibCalendarItem from "../itembox/tib-calendar-item.vue"; import TibCalendarItem from "../itembox/tib-calendar-item.vue";
import ToCalendar from "../overlay/to-calendar.vue"; import ToCalendar from "../overlay/to-calendar.vue";
// data
const calendarData = computed<TGApp.App.Calendar.Item[]>(() => AppCalendarData);
const weekNow = ref<number>(0); const weekNow = ref<number>(0);
const btnNow = ref<number>(0); const btnNow = ref<number>(0);
const dateNow = ref<string>(""); const dateNow = ref<string>("");
// page
const page = ref<number>(1);
const length = ref<number>(0);
// calendar // calendar
const calendarNow = ref<TGApp.App.Calendar.Item[]>([]); const calendarNow = ref<TGApp.App.Calendar.Item[]>([]);
const characterCards = ref<TGApp.App.Calendar.Item[]>([]); const characterCards = ref<TGApp.App.Calendar.Item[]>([]);
@@ -81,7 +63,7 @@ const weaponCards = ref<TGApp.App.Calendar.Item[]>([]);
// calendar item // calendar item
const showItem = ref<boolean>(false); const showItem = ref<boolean>(false);
const switchType = ref<string>("avatar"); const switchType = ref<"avatar" | "weapon">("avatar");
const selectedItem = ref<TGApp.App.Calendar.Item>(<TGApp.App.Calendar.Item>{}); const selectedItem = ref<TGApp.App.Calendar.Item>(<TGApp.App.Calendar.Item>{});
const selectedType = ref<"avatar" | "weapon">("avatar"); const selectedType = ref<"avatar" | "weapon">("avatar");
@@ -145,18 +127,23 @@ onMounted(async () => {
// 获取当前日历 // 获取当前日历
function getCalendar(day: number): TGApp.App.Calendar.Item[] { function getCalendar(day: number): TGApp.App.Calendar.Item[] {
return calendarData.value.filter((item) => item.dropDays.includes(day)); return AppCalendarData.filter((item) => item.dropDays.includes(day));
} }
function selectAvatar(item: TGApp.App.Calendar.Item): void { function getGrid(): TGApp.App.Calendar.Item[] {
selectedItem.value = item; let selectedCards: TGApp.App.Calendar.Item[] = [];
selectedType.value = "avatar"; if (switchType.value === "avatar") {
showItem.value = true; selectedCards = characterCards.value;
} else {
selectedCards = weaponCards.value;
}
length.value = Math.ceil(selectedCards.length / 20);
return selectedCards.slice((page.value - 1) * 20, page.value * 20);
} }
function selectWeapon(item: TGApp.App.Calendar.Item): void { function selectItem(item: TGApp.App.Calendar.Item): void {
selectedItem.value = item; selectedItem.value = item;
selectedType.value = "weapon"; selectedType.value = switchType.value;
showItem.value = true; showItem.value = true;
} }
@@ -165,65 +152,20 @@ function getContents(day: number): void {
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");
weaponCards.value = calendarNow.value.filter((item) => item.itemType === "weapon"); weaponCards.value = calendarNow.value.filter((item) => item.itemType === "weapon");
} page.value = 1;
async function share(): Promise<void> {
emits("loadOuter", { show: true, text: "正在生成图片..." });
const div = <HTMLElement>document.querySelector(".calendar-box");
const showType = switchType.value === "avatar" ? "角色" : "武器";
const title = `【今日素材】${showType}${btnNow.value}`;
await generateShareImg(title, div);
emits("loadOuter", { show: false });
} }
</script> </script>
<style lang="css" scoped> <style lang="css" scoped>
.calendar-box { .tc-top {
display: flex;
flex-direction: column;
padding: 10px;
border-radius: 5px;
background: var(--box-bg-1);
gap: 5px;
}
.calendar-title {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
margin-bottom: 10px;
font-family: var(--font-title); font-family: var(--font-title);
font-size: 20px; font-size: 20px;
} }
.calendar-title-left { .tc-switch {
display: flex;
align-items: center;
justify-content: start;
color: var(--common-text-title);
column-gap: 10px;
}
.calendar-title-gift {
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.calendar-title-mid {
display: flex;
align-items: center;
justify-content: start;
column-gap: 15px;
}
.calendar-title-right {
display: flex;
align-items: center;
justify-content: start;
gap: 15px;
}
.calendar-title-switch {
display: flex; display: flex;
height: 36px; height: 36px;
align-items: center; align-items: center;
@@ -231,21 +173,17 @@ async function share(): Promise<void> {
color: var(--box-text-1); color: var(--box-text-1);
} }
.calendar-title-btn { .tc-btns {
border: 1px solid var(--common-shadow-4); display: flex;
border-radius: 5px; align-items: center;
background: var(--tgc-btn-1); justify-content: center;
color: var(--btn-text); column-gap: 5px;
}
.calendar-divider {
margin: 10px 0;
opacity: 0.2;
} }
.calendar-grid { .calendar-grid {
display: grid; display: grid;
place-items: center flex-start;
grid-gap: 10px; grid-gap: 10px;
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); grid-template-columns: repeat(10, 1fr);
} }
</style> </style>

View File

@@ -0,0 +1,54 @@
<template>
<div class="thc-container">
<div class="thc-title">
<slot name="title"></slot>
</div>
<div class="thc-append" v-if="props.append">
<slot name="title-append"></slot>
</div>
<div class="thc-box">
<slot name="default"></slot>
</div>
</div>
</template>
<script lang="ts" setup>
interface THomecardProps {
append?: boolean;
}
const props = defineProps<THomecardProps>();
</script>
<style lang="css" scoped>
.thc-container {
position: relative;
min-height: 100px;
padding: 20px 10px 10px;
border: 1px solid var(--common-shadow-1);
border-radius: 5px;
margin-top: 30px;
box-shadow: 5px 5px 10px var(--common-shadow-2);
}
.thc-title,
.thc-append {
position: absolute;
top: -20px;
display: flex;
align-items: center;
justify-content: center;
padding: 0 10px;
border-radius: 5px;
background: var(--box-bg-blue);
box-shadow: 0 0 5px var(--common-shadow-2);
font-family: var(--font-title);
font-size: 20px;
}
.thc-title {
left: 10px;
}
.thc-append {
right: 10px;
}
</style>

View File

@@ -1,70 +1,66 @@
<template> <template>
<div class="pool-box"> <THomecard :append="hasNew">
<div class="pool-title"> <template #title>限时祈愿</template>
<div class="pool-title-left"> <template #title-append>
<img src="../../assets/icons/icon-wish.svg" alt="wish" /> <v-switch
<span>限时祈愿</span> class="pool-switch"
</div> variant="outline"
<div class="pool-title-right"> :label="showNew ? '查看当前祈愿' : '查看后续祈愿'"
<v-switch @change="switchPool"
class="pool-switch" />
color="var(--common-shadow-4)" </template>
variant="outline" <template #default>
:label="showNew ? '查看当前祈愿' : '查看后续祈愿'" <div class="pool-grid">
v-show="hasNew" <div v-for="pool in poolSelect" :key="pool.postId" class="pool-card">
@change="switchPool" <div class="pool-cover" @click="createPost(pool.postId, pool.title)">
/> <img :src="pool.cover" alt="cover" />
</div> </div>
</div> <div class="pool-bottom">
<div class="pool-grid"> <div class="pool-character">
<div v-for="pool in poolSelect" :key="pool.postId" class="pool-card"> <div class="pool-icons">
<div class="pool-cover" @click="createPost(pool.postId, pool.title)"> <div
<img :src="pool.cover" alt="cover" /> v-for="character in pool.characters"
</div> :key="character.url"
<div class="pool-bottom"> class="pool-icon"
<div class="pool-character"> @click="toOuter(character, pool.title)"
<div class="pool-icons"> >
<div <TItembox
v-for="character in pool.characters" :title="character.info.name"
:key="character.url" v-if="character.info"
class="pool-icon" :model-value="getCBox(character.info)"
@click="toOuter(character, pool.title)" />
> <img v-else :src="character.icon" alt="character" />
<TItembox </div>
:title="character.info.name" </div>
v-if="character.info" </div>
:model-value="getCBox(character.info)" <div class="pool-time">
/> <div>
<img v-else :src="character.icon" alt="character" /> <v-icon>mdi-calendar-clock</v-icon>
{{ pool.time.str }}
</div>
<v-progress-linear :model-value="poolTimePass[pool.postId]" :rounded="true">
</v-progress-linear>
<div v-if="poolTimeGet[pool.postId] === '已结束'">
{{ poolTimeGet[pool.postId] }}
</div>
<div v-else>
<span>剩余时间</span>
<span>
{{ poolTimeGet[pool.postId] }}
</span>
</div> </div>
</div> </div>
</div> </div>
<div class="pool-time">
<div>
<v-icon>mdi-calendar-clock</v-icon>
{{ pool.time.str }}
</div>
<v-progress-linear :model-value="poolTimePass[pool.postId]" :rounded="true">
</v-progress-linear>
<div v-if="poolTimeGet[pool.postId] === '已结束'">
{{ poolTimeGet[pool.postId] }}
</div>
<div v-else>
<span>剩余时间</span>
<span>
{{ poolTimeGet[pool.postId] }}
</span>
</div>
</div>
</div> </div>
</div> </div>
</div> </template>
</div> </THomecard>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, onMounted, onUnmounted } from "vue"; import { ref, onMounted, onUnmounted } from "vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import THomecard from "./t-homecard.vue";
import Mys from "../../plugins/Mys"; import Mys from "../../plugins/Mys";
import { useHomeStore } from "../../store/modules/home"; import { useHomeStore } from "../../store/modules/home";
import { createPost, createTGWindow } from "../../utils/TGWindow"; import { createPost, createTGWindow } from "../../utils/TGWindow";
@@ -244,37 +240,6 @@ onUnmounted(() => {
</script> </script>
<style lang="css" scoped> <style lang="css" scoped>
.pool-box {
display: flex;
flex-direction: column;
padding: 10px;
border-radius: 5px;
background: var(--box-bg-1);
gap: 10px;
}
.pool-title {
display: flex;
align-items: center;
justify-content: space-between;
font-family: var(--font-title);
font-size: 20px;
}
.pool-title-left {
display: flex;
align-items: center;
justify-content: start;
color: var(--common-text-title);
column-gap: 10px;
}
.pool-title-left img {
width: 25px;
height: 25px;
filter: brightness(0.8);
}
.pool-title-right { .pool-title-right {
display: flex; display: flex;
align-items: center; align-items: center;
@@ -287,7 +252,6 @@ onUnmounted(() => {
height: 36px; height: 36px;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
color: var(--box-text-1);
} }
.pool-grid { .pool-grid {

View File

@@ -1,51 +1,51 @@
<template> <template>
<div class="position-box"> <THomecard>
<div class="position-title"> <template #title>近期活动</template>
<img src="../../assets/icons/board.svg" alt="act" /> <template #default>
<span>近期活动</span> <div class="position-grid">
</div> <v-card
<div class="position-grid"> v-for="card in positionCards"
<v-card :key="card.postId"
v-for="card in positionCards" class="position-card"
:key="card.postId" variant="outlined"
class="position-card" >
variant="outlined" <v-list class="position-list">
> <v-list-item :title="card.title" :subtitle="card.abstract">
<v-list class="position-list"> <template #prepend>
<v-list-item :title="card.title" :subtitle="card.abstract"> <v-avatar rounded="0" @click="createPost(card.postId, card.title)">
<template #prepend> <v-img :src="card.icon" class="position-icon" />
<v-avatar rounded="0" @click="createPost(card.postId, card.title)"> </v-avatar>
<v-img :src="card.icon" class="position-icon" /> </template>
</v-avatar> <template #append>
</template> <v-btn class="position-card-btn" @click="createPost(card.postId, card.title)">
<template #append> 查看
<v-btn class="position-card-btn" @click="createPost(card.postId, card.title)"> </v-btn>
查看 </template>
</v-btn> </v-list-item>
</template> </v-list>
</v-list-item> <v-divider />
</v-list> <v-card-text>
<v-divider /> <div class="position-card-text">
<v-card-text> <v-icon>mdi-calendar-clock</v-icon>
<div class="position-card-text"> <span>{{ card.time.start }}~{{ card.time.end }}</span>
<v-icon>mdi-calendar-clock</v-icon> </div>
<span>{{ card.time.start }}~{{ card.time.end }}</span> <div class="position-card-text">
</div> <v-icon>mdi-clock-outline</v-icon>
<div class="position-card-text"> <span v-if="positionTimeGet[card.postId] !== '已结束'">{{
<v-icon>mdi-clock-outline</v-icon> positionTimeGet[card.postId]
<span v-if="positionTimeGet[card.postId] !== '已结束'">{{ }}</span>
positionTimeGet[card.postId] <span v-else>已结束</span>
}}</span> </div>
<span v-else>已结束</span> </v-card-text>
</div> </v-card>
</v-card-text> </div>
</v-card> </template>
</div> </THomecard>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, onMounted, onUnmounted } from "vue"; import { ref, onMounted, onUnmounted } from "vue";
import THomecard from "./t-homecard.vue";
import Mys from "../../plugins/Mys"; import Mys from "../../plugins/Mys";
import { createPost } from "../../utils/TGWindow"; import { createPost } from "../../utils/TGWindow";
import { stamp2LastTime } from "../../utils/toolFunc"; import { stamp2LastTime } from "../../utils/toolFunc";
@@ -106,28 +106,6 @@ onUnmounted(() => {
</script> </script>
<style lang="css" scoped> <style lang="css" scoped>
.position-box {
padding: 10px;
border-radius: 5px;
background: var(--box-bg-1);
}
.position-title {
display: flex;
align-items: center;
justify-content: start;
color: var(--common-text-title);
font-family: var(--font-title);
font-size: 20px;
}
.position-title img {
width: 20px;
height: 20px;
margin: 0 10px;
filter: brightness(0.9);
}
.position-grid { .position-grid {
display: grid; display: grid;
margin-top: 10px; margin-top: 10px;
@@ -138,7 +116,7 @@ onUnmounted(() => {
.position-card { .position-card {
border: 1px solid var(--common-shadow-2); border: 1px solid var(--common-shadow-2);
border-radius: 5px; border-radius: 5px;
background: var(--box-bg-2); background: var(--box-bg-1);
} }
.position-list { .position-list {

View File

@@ -1,7 +1,7 @@
/** /**
* @file router/modules/sub.ts * @file router/modules/sub.ts
* @description 子路由模块,用于二级窗口 * @description 子路由模块,用于二级窗口
* @since Beta v0.4.4 * @since Beta v0.4.5
*/ */
const subRoutes = [ const subRoutes = [
@@ -26,11 +26,6 @@ const subRoutes = [
name: "帖子详情JSON", name: "帖子详情JSON",
component: async () => await import("../../views/t-post-json.vue"), component: async () => await import("../../views/t-post-json.vue"),
}, },
{
path: "/lottery/:lottery_id",
name: "抽奖详情",
component: async () => await import("../../views/t-lottery.vue"),
},
]; ];
export default subRoutes; export default subRoutes;