💄 feat(theme): 页面主题切换完成

This commit is contained in:
BTMuli
2023-04-22 00:24:40 +08:00
parent 857cdec786
commit 277888dead
24 changed files with 277 additions and 87 deletions

View File

@@ -40,11 +40,11 @@ import { TGAppDataList, TGGetDataList } from "./data";
const appStore = useAppStore();
const isMain = ref(true as boolean);
const theme = ref(appStore.theme as string);
onMounted(async () => {
// 获取当前主题
const theme = appStore.theme;
document.documentElement.className = theme;
document.documentElement.className = theme.value;
// 获取当前窗口
const win = window.getCurrent();
isMain.value = win.label === "tauri-genshin";

View File

@@ -1,12 +1,13 @@
/*
* @description 米游社解析 css
* @since Alpha v0.1.1
* @since Alpha v0.1.3
*/
/* todo scoped 不生效 */
.mys-post-body {
margin: 20px auto;
width: 800px;
font-family: "Genshin-Light", serif;
color: var(--post-default-text);
}
:deep(.mys-post-div) {
@@ -69,7 +70,7 @@
padding: 10px;
border-radius: 10px;
display: flex;
background: #faf7e8;
background: var(--content-bg-2);
}
:deep(.mys-post-unknown) {

View File

@@ -26,16 +26,6 @@
background: #555;
}
/*
* @description 米游社解析 json
* @since Alpha v0.1.1
*/
.dev-json {
padding: 20px;
border-radius: 20px;
font-family: Consolas, serif;
}
/* card action 内的按钮 */
.card-btn {
background: #4a5366;

View File

@@ -0,0 +1,30 @@
/**
* @file assets themes light.css
* @description 主题样式文件
* @author BTMuli<bt-muli@outlook.com>
* @since Alpha v0.1.3
*/
/* 主题色 */
html.dark {
--sidebar-bg: #1e1e1e;
--sidebar-icon: #e1e1e1;
--page-bg:#2a2a2a;
--back-top-shadow: #000000;
--theme-switch-icon: #e1e1e1;
--post-default-text: #faf7e8;
--content-bg-1: #1e1e1e;
--content-bg-2: #393b40;
--content-bg-3: #2a2a2a;
--content-text-1: #1e1e1e;
--content-text-2: #faf7e8;
--content-text-3: #e1e1e1;
--btn-bg-1: #3b3d3b;
--btn-bg-2: #000000;
--btn-bg-3: #1e1e1e;
--btn-text-1: #393b40;
--card-text-1: #393b40;
}

View File

@@ -0,0 +1,30 @@
/**
* @file assets themes dark.css
* @description 主题样式文件
* @author BTMuli<bt-muli@outlook.com>
* @since Alpha v0.1.3
*/
/* 主题色 */
html.default {
--sidebar-bg: #485466;
--sidebar-icon: #ece5d8;
--page-bg:#ece5d8;
--back-top-shadow: #546d8b;
--theme-switch-icon: #393b40;
--post-default-text: #1e1e1e;
--content-bg-1: #546d8b;
--content-bg-2: #faf7e8;
--content-bg-3: #5b738f;
--content-text-1: #fec90b;
--content-text-2: #393b40;
--content-text-3: #546d8b;
--btn-bg-1: #fec90b;
--btn-bg-2: #4a5366;
--btn-bg-3: #546d8b;
--btn-text-1: #faf7e8;
--card-text-1: #485466;
}

View File

@@ -64,7 +64,7 @@ onMounted(() => {
cursor: pointer;
transform: scale(0.9);
transition: all 0.3s ease-in-out;
box-shadow: 0 0 10px 5px #546d8b;
box-shadow: 0 0 10px 5px var(--back-top-shadow);
}
.back-top img {

View File

@@ -11,8 +11,9 @@
:key="text.week"
class="calendar-btn"
:style="{
border: text.week === weekNow ? '2px solid #fec90b' : '0',
background: text.week === btnNow ? '#fec90b' : '#4A5366',
border: text.week === weekNow ? '2px solid var(--btn-bg-1)' : '0',
background: text.week === btnNow ? 'var(--btn-bg-1)' : 'var(--btn-bg-2)',
color: '#faf7e8'
}"
@click="getContents(text.week)"
>
@@ -239,14 +240,14 @@ function getContents (day: number) {
.calendar-card {
margin-top: 10px;
font-family: Genshin-Light, serif;
background: #546d8b;
background: var(--content-bg-1);
border-radius: 10px;
}
.calendar-btn {
margin-left: 10px;
font-family: Genshin-Light, serif;
color: #faf7e8;
color: var(--btn-text-1);
border-radius: 10px;
}
@@ -262,8 +263,8 @@ function getContents (day: number) {
.calendar-single {
margin-bottom: 10px;
background: #faf7e8;
color: #546d8b;
background: var(--content-bg-2);
color: var(--content-bg-1);
border-radius: 10px;
}
@@ -276,8 +277,8 @@ function getContents (day: number) {
}
.calendar-content {
background: #546D8B;
color:#faf7e8;
background: var(--content-bg-1);
color:var(--content-bg-2);
margin: 5px;
border-radius: 10px;
padding: 10px;
@@ -414,7 +415,7 @@ function getContents (day: number) {
display: flex;
justify-content: center;
align-items: center;
background: rgba(20, 20, 20, 0.5);
background: rgb(20 20 20 / 50%);
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
color: #fff;

View File

@@ -73,7 +73,7 @@ const onConfirm = () => {
height: 20vh;
top: 40vh;
left: 30vw;
background: #fff;
background: var(--content-bg-2);
border-radius: 10px;
padding: 10px;
display: flex;
@@ -92,7 +92,7 @@ const onConfirm = () => {
text-align: center;
height: 20%;
width: 100%;
color: #393b40;
color: var(--content-text-2);
margin: 20px;
font-size: 30px;
}
@@ -109,8 +109,8 @@ const onConfirm = () => {
width: 30%;
min-width: 150px;
min-height: 30px;
background: #4a5366;
color: #faf7e8;
background: var(--btn-bg-2);
color: var(--btn-text-1);
border-radius: 50px;
display: flex;
align-items: center;

View File

@@ -9,9 +9,9 @@
<v-card
v-for="pool in poolCards"
:key="pool.post_id"
style="background: #faf7e8; color: #546d8b; border-radius: 10px"
style="background: var(--content-bg-2); color: #546d8b; border-radius: 10px"
>
<v-list style="background: #faf7e8; color: #546d8b">
<v-list style="background: var(--content-bg-2); color: #546d8b">
<v-list-item :title="pool.title" :subtitle="pool.subtitle">
<template #prepend>
<v-img :src="pool.voice.icon" style="transform: translate(0, -10px); width: 60px; height: 60px" />
@@ -188,7 +188,7 @@ function toPost (pool: GachaCard) {
.pool-card {
font-family: Genshin, serif;
width: 100%;
background: #546d8b;
background: var(--content-bg-1);
border-radius: 10px;
margin-top: 10px;
}

View File

@@ -9,9 +9,9 @@
<v-card
v-for="card in positionCards"
:key="card.post_id"
style="background: #faf7e8; color: #546d8b; border-radius: 10px"
style="background: var(--content-bg-2); color: #546d8b; border-radius: 10px"
>
<v-list style="background: #faf7e8; color: #546d8b">
<v-list style="background: var(--content-bg-2); color: #546d8b">
<v-list-item :title="card.title" :subtitle="card.abstract">
<template #prepend>
<v-avatar rounded="0" style="cursor: pointer" @click="toPost(card)">
@@ -130,7 +130,7 @@ async function toPost (card: PositionCard) {
.position-card {
margin-top: 10px;
font-family: Genshin, serif;
background: #546d8b;
background: var(--content-bg-1);
border-radius: 10px;
}

View File

@@ -5,14 +5,14 @@
<v-list-item @click="collapse">
<template v-if="rail" #prepend>
<v-list-item-action>
<v-icon color="rgb(205, 182, 145)">
<v-icon style="color:var(--sidebar-icon)">
mdi-chevron-right
</v-icon>
</v-list-item-action>
</template>
<template v-else #append>
<v-list-item-action>
<v-icon color="rgb(205, 182, 145)">
<v-icon style="color:var(--sidebar-icon)">
mdi-chevron-left
</v-icon>
</v-list-item-action>
@@ -85,7 +85,7 @@
<v-list-item title="图鉴" v-bind="props">
<template #prepend>
<!-- TODO: 后续更换图标-->
<v-icon color="rgb(205, 182, 145)">
<v-icon style="color:var(--sidebar-icon)">
mdi-book-open-variant
</v-icon>
</template>
@@ -99,7 +99,7 @@
<v-list-item title="角色图鉴" value="wiki-character" link href="/wiki/character">
<template #prepend>
<!-- TODO: 后续更换图标-->
<v-icon style="color:#FDE7AC !important">
<v-icon style="color:var(--sidebar-icon)">
mdi-account
</v-icon>
</template>
@@ -107,7 +107,7 @@
<v-list-item title="武器图鉴" value="wiki-weapon" link href="/wiki/weapon">
<template #prepend>
<!-- TODO: 后续更换图标 -->
<v-icon style="color:#FDE7AC !important">
<v-icon style="color:var(--sidebar-icon)">
mdi-sword
</v-icon>
</template>
@@ -122,8 +122,8 @@
</v-list-item> -->
<v-list-item :title="themeTitle" value="theme" @click="switchTheme">
<template #prepend>
<v-icon color="rgb(205, 182, 145)">
{{ themeGet === 'default' ? 'mdi-weather-sunny' : 'mdi-weather-night' }}
<v-icon style="color:var(--sidebar-icon)">
{{ themeGet === 'default' ? 'mdi-weather-night' : 'mdi-weather-sunny' }}
</v-icon>
</template>
</v-list-item>
@@ -175,8 +175,7 @@ function collapse () {
}
function switchTheme () {
themeGet.value = themeGet.value === "default" ? "dark" : "default";
appStore.theme = themeGet.value;
appStore.changeTheme();
document.documentElement.className = themeGet.value;
}

View File

@@ -0,0 +1,56 @@
<template>
<div class="switch-box">
<div class="switch-btn" @click="swithcTheme()">
<v-icon style="color:var(--theme-switch-icon)">
{{ themeGet === 'default' ? 'mdi-weather-night' : 'mdi-weather-sunny' }}
</v-icon>
</div>
</div>
</template>
<script lang="ts" setup>
// vue
import { computed } from "vue";
// store
import { useAppStore } from "../store/modules/app";
// store
const appStore = useAppStore();
// theme
const themeGet = computed({
get () {
return appStore.theme;
},
set (value: string) {
appStore.theme = value;
},
});
function swithcTheme () {
appStore.changeTheme();
document.documentElement.className = themeGet.value;
}
</script>
<style lang="css" scoped>
.switch-box {
position: absolute;
top: 20px;
left: 20px;
cursor: pointer;
border-radius: 50%;
border: var(--theme-switch-icon) 2px solid;
}
.switch-box:hover {
opacity: 0.8;
}
.switch-btn {
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
margin: 5px;
}
</style>

View File

@@ -3,7 +3,7 @@
<TLoading :title="loadingTitle" />
</div>
<div v-else>
<v-tabs v-model="tab" align-tabs="start" class="global-font mb-2">
<v-tabs v-model="tab" align-tabs="start" class="anno-tab">
<v-tab value="activity" title="活动公告" />
<v-tab value="game" title="游戏公告" />
<v-spacer />
@@ -159,6 +159,12 @@ async function toJson (item: BTMuli.Genshin.Announcement.ListCard) {
</script>
<style lang="css" scoped>
.anno-tab {
font-family: Genshin, serif;
margin-bottom: 20px;
color: var(--content-text-3)
}
.anno-grid {
font-family: Genshin, serif;
display: grid;
@@ -168,8 +174,8 @@ async function toJson (item: BTMuli.Genshin.Announcement.ListCard) {
.anno-card {
border-radius: 10px;
background: #faf7e8;
color: #546d8b;
background: var(--content-bg-2);
color: var(--content-text-2);
border-bottom: #4b5366 1px solid;
}
@@ -193,7 +199,7 @@ async function toJson (item: BTMuli.Genshin.Announcement.ListCard) {
.anno-btn {
margin-left: 5px;
background: #546d8b;
background: var(--btn-bg-3);
color: #faf7e8;
}
@@ -205,10 +211,10 @@ async function toJson (item: BTMuli.Genshin.Announcement.ListCard) {
/* switch */
.switch-btn {
font-family: Genshin, serif;
background: #ffca0a;
background: var(--btn-bg-1);
height: 40px;
margin-right: 10px;
margin-top: 5px;
color: #546d8b;
color: var(--content-text-3);
}
</style>

View File

@@ -375,15 +375,15 @@ function delDB () {
.config-list {
margin: 10px;
font-family: Genshin-Light, serif;
background: #faf7e8;
color: #546d8b;
background: var(--content-bg-2);
color: var(--content-text-3);
border-radius: 10px;
}
.config-header {
margin-top: 10px;
font-family: Genshin, serif;
background: #faf7e8;
background: var(--content-bg-2);
color: #fec90b;
font-size: large;
}
@@ -393,7 +393,7 @@ function delDB () {
height: 40px;
margin-right: 15px;
padding: 5px;
background: #5b738f;
background: var(--content-bg-3);
border-radius: 10px;
}
</style>

View File

@@ -143,7 +143,7 @@ function toOuter (item: BTMuli.Genshin.Wiki.Character.BriefInfo) {
display: flex;
justify-content: center;
align-items: center;
background: rgba(20, 20, 20, 0.5);
background: rgb(20 20 20 / 50%);
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
color: #fff;

View File

@@ -3,7 +3,7 @@
<TLoading title="正在加载卡牌列表" />
</div>
<div v-else>
<v-tabs v-model="tab" align-tabs="start" class="global-font">
<v-tabs v-model="tab" align-tabs="start" class="cards-tab">
<div v-show="!doSearch">
<v-tab value="character" title="角色牌" />
<v-tab value="action" title="行动牌" />
@@ -145,6 +145,12 @@ async function searchCard () {
}
</script>
<style lang="css" scoped>
.cards-tab {
font-family: Genshin,serif;
margin-bottom: 20px;
color: var(--content-text-3);
}
.cards-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));

View File

@@ -142,7 +142,7 @@ function toOuter (item: BTMuli.Genshin.Wiki.Weapon.BriefInfo) {
display: flex;
justify-content: center;
align-items: center;
background: rgba(20, 20, 20, 0.5);
background: rgb(20 20 20 / 50%);
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
color: #fff;

View File

@@ -2,10 +2,25 @@
* @file plugins Mys utils PostParser.ts
* @description 用于解析Mys数据的工具
* @author BTMuli<bt-muli@outlook.com>
* @since Alpha v0.1.2
* @since Alpha v0.1.3
*/
import { type PostData, type PostStructuredContent } from "../interface/post";
/**
* @description 在 dark 模式下显示模糊的 color
* @since Alpha v0.1.3
* @constant {string[]} darkColorList 模糊的 color
* @readonly
* @returns {string[]} 模糊的 color
*/
const darkColorList: string[] = [
"#111111",
"#333333",
"#0f141a",
"#494949",
"#666666",
];
/**
* @description 检测链接是否是米游社帖子
* @since Alpha v0.1.2
@@ -146,7 +161,7 @@ function UnknownParser (data: PostStructuredContent): HTMLDivElement {
/**
* @description 解析文本
* @since Alpha
* @since Alpha v0.1.3
* @param {PostStructuredContent} data Mys数据
* @returns {HTMLSpanElement} 解析后的文本
*/
@@ -160,7 +175,14 @@ function TextParser (data: PostStructuredContent): HTMLSpanElement {
// 设置文本属性
if (data.attributes) {
if (data.attributes.bold) text.style.fontWeight = "bold";
if (data.attributes.color) text.style.color = data.attributes.color;
if (data.attributes.color) {
let colorGet = data.attributes.color;
// 如果 colorGet 在 darkColorList 中,就设置为对应的颜色
if (darkColorList.includes(colorGet)) {
colorGet = "var(--post-default-text)";
}
text.style.color = colorGet;
}
if (data.attributes.link) {
return LinkTextParser(data);
}

View File

@@ -1,16 +1,17 @@
<template>
<TSwitchTheme />
<div v-if="loading">
<TLoading :empty="loadingEmpty" :title="loadingTitle" />
</div>
<div v-else class="dev-json">
<div v-else class="anno-json">
<div class="anno-title">
活动列表 JSON
</div>
<JsonViewer :value="jsonList" copyable boxed />
<JsonViewer :value="jsonList" copyable boxed class="anno-data" />
<div class="anno-title">
活动内容 JSON
</div>
<JsonViewer :value="jsonContent" copyable boxed />
<JsonViewer :value="jsonContent" copyable boxed class="anno-data" />
</div>
</template>
<script lang="ts" setup>
@@ -19,6 +20,7 @@ import { ref, onMounted, reactive } from "vue";
import { useRoute } from "vue-router";
import JsonViewer from "vue-json-viewer";
import TLoading from "../components/t-loading.vue";
import TSwitchTheme from "../components/t-switchTheme.vue";
// tauri
import { appWindow } from "@tauri-apps/api/window";
// utils
@@ -45,7 +47,7 @@ onMounted(async () => {
// 获取数据
loadingTitle.value = "正在获取数据...";
const listData = await TGRequest.Anno.getList();
listData.list.map((item: BTMuli.Genshin.Announcement.Announcement) => {
listData.list.map((item: BTMuli.Genshin.Announcement) => {
return item.list.map((single: BTMuli.Genshin.Announcement.ListItem) => {
return single.ann_id === annoId ? (jsonList = single) : null;
});
@@ -57,6 +59,12 @@ onMounted(async () => {
});
</script>
<style lang="css" scoped>
.anno-json {
padding: 20px;
border-radius: 20px;
font-family: Consolas, serif;
}
.anno-title {
font-size: 20px;
color: #546d8b;
@@ -64,4 +72,8 @@ onMounted(async () => {
font-weight: 600;
margin: 20px 0;
}
.jv-container {
background: var(--content-bg-2) !important;
}
</style>

View File

@@ -1,5 +1,6 @@
<!-- eslint-disable vue/no-v-html -->
<template>
<TSwitchTheme />
<div v-if="loading" class="loading">
<TLoading :title="loadingTitle" :empty="loadingEmpty" />
</div>
@@ -19,6 +20,7 @@
import { ref, onMounted } from "vue";
import { useRoute } from "vue-router";
import TLoading from "../components/t-loading.vue";
import TSwitchTheme from "../components/t-switchTheme.vue";
// tauri
import { appWindow } from "@tauri-apps/api/window";
// plugins

View File

@@ -1,4 +1,5 @@
<template>
<TSwitchTheme />
<div v-if="loading">
<TLoading :empty="loadingEmpty" :title="loadingTitle" />
</div>
@@ -42,7 +43,7 @@
JSON
</v-btn>
</div>
<div v-show="showJson" class="dev-json">
<div v-show="showJson" class="lottery-json">
<JsonViewer :value="jsonData" copyable boxed />
</div>
<div v-if="timeStatus === '已开奖'" class="lottery-div">
@@ -73,6 +74,7 @@ import { ref, onMounted, reactive, onUpdated } from "vue";
import { useRoute } from "vue-router";
import JsonViewer from "vue-json-viewer";
import TLoading from "../components/t-loading.vue";
import TSwitchTheme from "../components/t-switchTheme.vue";
// tauri
import { appWindow } from "@tauri-apps/api/window";
// store
@@ -173,17 +175,17 @@ onUpdated(() => {
</script>
<style lang="css">
.lottery-div {
background: #faf7e8;
background: var(--content-bg-2);
border-radius: 10px;
margin: 10px;
margin-bottom: 10px;
padding: 10px;
}
.lottery-title {
font-family: Genshin, serif;
font-size: 20px;
color: #546d8b;
margin: 10px;
color: var(--content-text-3);
margin-left: 40px;
}
.reward-title {
@@ -201,7 +203,7 @@ onUpdated(() => {
}
.lottery-list {
background: #546d8b;
background: var(--content-bg-1);
border-radius: 10px;
margin: 10px;
padding: 10px;
@@ -237,13 +239,10 @@ onUpdated(() => {
}
.lottery-sub-list {
/* background: #546d8b; */
background: #faf7e8;
background: var(--content-bg-2);
border-radius: 40px;
height: 40px;
margin: 5px;
/* color: #faf7e8; */
color: #546d8b;
font-family: Genshin-Light, serif;
align-items: center;
display: flex;
@@ -267,9 +266,18 @@ onUpdated(() => {
.lottery-user-nickname {
display: inline-block;
font-size: 14px;
font-family: Genshin-Light, 仿宋;
/* color: #faf7e8; */
color: #546d8b;
font-family: Genshin-Light, "仿宋";
color: var(--content-text-3);
overflow: hidden;
}
.lottery-json {
padding: 20px;
border-radius: 20px;
font-family: Consolas, serif;
}
.jv-container {
background: var(--content-bg-2) !important;
}
</style>

View File

@@ -3,7 +3,7 @@
<TLoading :title="loadingTitle" />
</div>
<div v-else>
<v-tabs v-model="tab" align-tabs="start" class="news-tabs">
<v-tabs v-model="tab" align-tabs="start" class="news-tab">
<v-tab value="notice" title="公告" />
<v-tab value="activity" title="活动" />
<v-tab v-if="showNews" value="news" title="新闻" />
@@ -349,9 +349,10 @@ async function searchPost () {
</script>
<style lang="css" scoped>
.news-tabs {
.news-tab {
font-family: Genshin, serif;
margin-bottom: 10px;
margin-bottom: 20px;
color: var(--content-text-3)
}
.news-grid {
@@ -363,8 +364,8 @@ async function searchPost () {
.news-card {
border-radius: 10px;
background: #faf7e8;
color: #546d8b;
background: var(--content-bg-2);
color: var(--content-text-2);
}
.news-cover {
@@ -388,11 +389,11 @@ async function searchPost () {
/* switch */
.switch-btn {
font-family: Genshin, serif;
background: #ffca0a;
background: var(--btn-bg-1);
height: 40px;
margin-right: 10px;
margin-top: 5px;
color: #546d8b;
color: var(--content-text-3);
}
/* load more */
@@ -408,8 +409,8 @@ async function searchPost () {
}
.load-news button {
background: #546d8b !important;
color: #faf7e8 !important;
background: var(--btn-bg-3);
color: #faf7e8;
}
.load-news button img {

View File

@@ -1,8 +1,12 @@
<template>
<TSwitchTheme />
<div v-if="loading">
<TLoading :empty="loadingEmpty" :title="loadingTitle" />
</div>
<div v-else class="dev-json">
<div v-else class="post-json">
<div class="post-title">
帖子返回内容 JSON
</div>
<JsonViewer :value="jsonData" copyable boxed />
</div>
</template>
@@ -12,6 +16,7 @@ import { ref, onMounted, reactive } from "vue";
import { useRoute } from "vue-router";
import JsonViewer from "vue-json-viewer";
import TLoading from "../components/t-loading.vue";
import TSwitchTheme from "../components/t-switchTheme.vue";
// tauri
import { appWindow } from "@tauri-apps/api/window";
// plugins
@@ -42,3 +47,22 @@ onMounted(async () => {
}, 200);
});
</script>
<style>
.post-json {
padding: 20px;
border-radius: 20px;
font-family: Consolas, serif;
}
.post-title {
font-size: 20px;
color: #546d8b;
font-family: Genshin-Light, serif;
font-weight: 600;
margin: 20px 0;
}
.jv-container {
background: var(--content-bg-2) !important;
}
</style>

View File

@@ -1,5 +1,6 @@
<!-- eslint-disable vue/no-v-html -->
<template>
<TSwitchTheme />
<div v-if="loading">
<TLoading :empty="loadingEmpty" :title="loadingTitle" />
</div>
@@ -14,6 +15,7 @@ import TLoading from "../components/t-loading.vue";
import { appWindow } from "@tauri-apps/api/window";
// plugins
import MysOper from "../plugins/Mys";
import TSwitchTheme from "../components/t-switchTheme.vue";
// loading
const loading = ref(true as boolean);