Skip to content

Commit 822b6b4

Browse files
committed
feat: add theme toggle functionality and improve dark mode support
1 parent 9276165 commit 822b6b4

File tree

1 file changed

+126
-22
lines changed

1 file changed

+126
-22
lines changed

frontend/astrbot-cloud/src/pages/index.vue

Lines changed: 126 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
import axios from 'axios';
33
import { pinyin } from 'pinyin-pro';
44
import { ref, computed, onMounted, watch } from 'vue';
5+
import { useTheme } from 'vuetify';
6+
7+
// 主题
8+
const theme = useTheme();
9+
const isDark = computed(() => theme.global.current.value.dark);
510
611
// 插件市场数据
712
const pluginMarketData = ref([]);
@@ -300,14 +305,19 @@ watch(marketSearch, (newVal) => {
300305
}, 300);
301306
});
302307
308+
// 切换主题
309+
const toggleTheme = () => {
310+
theme.global.name.value = isDark.value ? 'light' : 'dark';
311+
};
312+
303313
// 页面加载时获取数据
304314
onMounted(() => {
305315
getPluginMarketData();
306316
});
307317
</script>
308318
309319
<template>
310-
<v-container fluid style="background-color: #f9fafc;">
320+
<v-container fluid :class="['page-container', { 'dark-mode': isDark }]">
311321
<!-- 导航栏 -->
312322
<nav class="top-nav">
313323
<div class="nav-container">
@@ -322,6 +332,17 @@ onMounted(() => {
322332
323333
<!-- 导航项 -->
324334
<div class="nav-items">
335+
<v-btn
336+
icon
337+
variant="text"
338+
@click="toggleTheme"
339+
size="small"
340+
>
341+
<v-icon>{{ isDark ? 'mdi-weather-sunny' : 'mdi-weather-night' }}</v-icon>
342+
<v-tooltip activator="parent" location="bottom">
343+
{{ isDark ? '切换到浅色模式' : '切换到深色模式' }}
344+
</v-tooltip>
345+
</v-btn>
325346
<a href="https://astrbot.app" target="_blank" class="nav-item">
326347
<v-icon size="small" class="mr-1">mdi-home</v-icon>
327348
<span class="d-none d-sm-inline">主页</span>
@@ -344,11 +365,11 @@ onMounted(() => {
344365
345366
<v-row>
346367
<v-col cols="12">
347-
<v-card variant="flat" style="background-color: transparent">
368+
<v-card variant="flat" color="transparent">
348369
<v-card-text style="padding: 0px 12px;">
349370
<!-- 标题和搜索栏 -->
350371
<div class="mb-4 d-flex flex-column align-center">
351-
<h1 class="text-h4 mb-4 text-center" style="font-weight: 1000; padding-top: 80px;">AstrBot 插件市场</h1>
372+
<h1 class="page-title text-h4 mb-4 text-center">AstrBot 插件市场</h1>
352373
<div style="width: 100%; max-width: 500px; padding: 0 12px;">
353374
<v-text-field
354375
v-model="marketSearch"
@@ -365,9 +386,9 @@ onMounted(() => {
365386
366387
<!-- 插件市场内容 -->
367388
<div class="mt-4">
368-
<div class="d-flex align-center mb-2" style="justify-content: space-between; flex-wrap: wrap; gap: 8px; padding: 0 4px;">
389+
<div class="section-header d-flex align-center mb-2" style="justify-content: space-between; flex-wrap: wrap; gap: 8px; padding: 0 4px;">
369390
<div class="d-flex align-center" style="gap: 6px;">
370-
<h2>所有插件({{ filteredMarketPlugins.length }})</h2>
391+
<h2 class="section-title">所有插件({{ filteredMarketPlugins.length }})</h2>
371392
<v-btn icon variant="text" @click="refreshPluginMarket" :loading="refreshingMarket" size="small">
372393
<v-icon size="small">mdi-refresh</v-icon>
373394
</v-btn>
@@ -433,9 +454,9 @@ onMounted(() => {
433454
434455
<v-col v-else v-for="plugin in paginatedPlugins" :key="plugin.name" cols="12" md="6" lg="4">
435456
<v-card
436-
class="rounded-lg d-flex flex-column plugin-card"
457+
class="plugin-card rounded-lg d-flex flex-column"
437458
elevation="0"
438-
style="height: 12rem; position: relative; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);"
459+
style="height: 12rem; position: relative;"
439460
>
440461
<!-- 推荐标记 -->
441462
<v-chip
@@ -596,18 +617,18 @@ onMounted(() => {
596617
scrollable
597618
>
598619
<v-card class="publish-dialog-card">
599-
<v-card-title class="text-h5 d-flex align-center pa-4 pa-sm-6" style="color: black;">
620+
<v-card-title class="dialog-title text-h5 d-flex align-center pa-4 pa-sm-6">
600621
<div>
601622
<div class="text-h6 text-sm-h5 font-weight-bold">发布插件到 AstrBot 插件市场</div>
602-
<div class="text-caption mt-1" style="opacity: 0.9;">填写插件信息自动提交到 GitHub</div>
623+
<div class="text-caption mt-1" style="opacity: 0.9;">填写插件信息,自动提交到 GitHub</div>
603624
</div>
604625
</v-card-title>
605626
606627
<v-card-text class="pt-6 pb-4" style="max-height: 600px; overflow-y: auto;">
607628
<v-form v-model="formValid">
608629
<!-- 基本信息卡片 -->
609-
<v-card class="mb-4" elevation="0" style="border: 1px solid rgba(0,0,0,0.1);">
610-
<v-card-title class="text-subtitle-1 bg-grey-lighten-4 py-3">
630+
<v-card class="form-section mb-4" elevation="0">
631+
<v-card-title class="form-section-title text-subtitle-1 py-3">
611632
<v-icon size="small" class="mr-2">mdi-information</v-icon>
612633
基本信息
613634
</v-card-title>
@@ -652,8 +673,8 @@ onMounted(() => {
652673
</v-card>
653674
654675
<!-- 作者信息卡片 -->
655-
<v-card class="mb-4" elevation="0" style="border: 1px solid rgba(0,0,0,0.1);">
656-
<v-card-title class="text-subtitle-1 bg-grey-lighten-4 py-3">
676+
<v-card class="form-section mb-4" elevation="0">
677+
<v-card-title class="form-section-title text-subtitle-1 py-3">
657678
<v-icon size="small" class="mr-2">mdi-account</v-icon>
658679
作者信息
659680
</v-card-title>
@@ -681,8 +702,8 @@ onMounted(() => {
681702
</v-card>
682703
683704
<!-- 仓库信息卡片 -->
684-
<v-card class="mb-4" elevation="0" style="border: 1px solid rgba(0,0,0,0.1);">
685-
<v-card-title class="text-subtitle-1 bg-grey-lighten-4 py-3">
705+
<v-card class="form-section mb-4" elevation="0">
706+
<v-card-title class="form-section-title text-subtitle-1 py-3">
686707
<v-icon size="small" class="mr-2">mdi-github</v-icon>
687708
仓库信息
688709
</v-card-title>
@@ -702,8 +723,8 @@ onMounted(() => {
702723
</v-card>
703724
704725
<!-- 标签卡片 -->
705-
<v-card class="mb-4" elevation="0" style="border: 1px solid rgba(0,0,0,0.1);">
706-
<v-card-title class="text-subtitle-1 bg-grey-lighten-4 py-3">
726+
<v-card class="form-section mb-4" elevation="0">
727+
<v-card-title class="form-section-title text-subtitle-1 py-3">
707728
<v-icon size="small" class="mr-2">mdi-tag-multiple</v-icon>
708729
插件标签(可选)
709730
</v-card-title>
@@ -775,7 +796,7 @@ onMounted(() => {
775796
776797
<v-divider></v-divider>
777798
778-
<v-card-actions class="pa-4 bg-grey-lighten-5">
799+
<v-card-actions class="dialog-actions pa-4">
779800
<v-spacer></v-spacer>
780801
<v-btn
781802
color="grey"
@@ -806,6 +827,16 @@ onMounted(() => {
806827
</template>
807828
808829
<style scoped>
830+
/* 页面容器 */
831+
.page-container {
832+
background-color: #f9fafc;
833+
transition: background-color 0.3s ease;
834+
}
835+
836+
.page-container.dark-mode {
837+
background-color: #121212;
838+
}
839+
809840
/* 导航栏样式 */
810841
.top-nav {
811842
position: fixed;
@@ -816,6 +847,13 @@ onMounted(() => {
816847
background: rgba(255, 255, 255, 0.95);
817848
backdrop-filter: blur(10px);
818849
animation: fadeInUp 0.3s ease-in-out;
850+
transition: background-color 0.3s ease, box-shadow 0.3s ease;
851+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
852+
}
853+
854+
.dark-mode .top-nav {
855+
background: rgba(18, 18, 18, 0.95);
856+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
819857
}
820858
821859
.nav-container {
@@ -860,11 +898,35 @@ onMounted(() => {
860898
white-space: nowrap;
861899
}
862900
901+
.dark-mode .nav-item {
902+
color: rgba(255, 255, 255, 0.7);
903+
}
904+
863905
.nav-item:hover {
864906
background: rgba(0, 0, 0, 0.05);
865907
color: rgb(var(--v-theme-primary));
866908
}
867909
910+
.dark-mode .nav-item:hover {
911+
background: rgba(255, 255, 255, 0.1);
912+
}
913+
914+
/* 页面标题 */
915+
.page-title {
916+
font-weight: 1000;
917+
padding-top: 80px;
918+
transition: color 0.3s ease;
919+
}
920+
921+
/* 区块标题 */
922+
.section-header {
923+
transition: color 0.3s ease;
924+
}
925+
926+
.section-title {
927+
transition: color 0.3s ease;
928+
}
929+
868930
/* 移动端导航适配 */
869931
@media (max-width: 600px) {
870932
.nav-container {
@@ -900,6 +962,37 @@ onMounted(() => {
900962
overflow: hidden;
901963
}
902964
965+
.dialog-title {
966+
transition: background-color 0.3s ease, color 0.3s ease;
967+
}
968+
969+
.dialog-actions {
970+
background-color: rgba(0, 0, 0, 0.02);
971+
transition: background-color 0.3s ease;
972+
}
973+
974+
.dark-mode .dialog-actions {
975+
background-color: rgba(255, 255, 255, 0.05);
976+
}
977+
978+
.form-section {
979+
border: 1px solid rgba(0, 0, 0, 0.1);
980+
transition: border-color 0.3s ease, background-color 0.3s ease;
981+
}
982+
983+
.dark-mode .form-section {
984+
border-color: rgba(255, 255, 255, 0.12);
985+
}
986+
987+
.form-section-title {
988+
background-color: rgba(0, 0, 0, 0.03);
989+
transition: background-color 0.3s ease;
990+
}
991+
992+
.dark-mode .form-section-title {
993+
background-color: rgba(255, 255, 255, 0.05);
994+
}
995+
903996
.publish-dialog-card :deep(.v-card-text) {
904997
scrollbar-width: thin;
905998
scrollbar-color: rgba(0, 0, 0, 0.2) transparent;
@@ -948,10 +1041,21 @@ onMounted(() => {
9481041
cursor: pointer;
9491042
border: 2px solid transparent;
9501043
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
1044+
background-color: #ffffff;
1045+
}
1046+
1047+
.dark-mode .plugin-card {
1048+
background-color: #1e1e1e;
9511049
}
9521050
9531051
.plugin-card:hover {
9541052
border-color: rgb(var(--v-theme-secondary));
1053+
transform: translateY(-2px);
1054+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
1055+
}
1056+
1057+
.dark-mode .plugin-card:hover {
1058+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
9551059
}
9561060
9571061
/* 推荐标签动画 */
@@ -1017,24 +1121,24 @@ onMounted(() => {
10171121
/* 移动端适配 */
10181122
@media (max-width: 960px) {
10191123
/* 标题适配 */
1020-
h1.text-h4 {
1124+
.page-title.text-h4 {
10211125
font-size: 1.75rem !important;
10221126
padding-top: 80px !important;
10231127
}
10241128
1025-
h2 {
1129+
.section-title {
10261130
font-size: 1.25rem !important;
10271131
}
10281132
}
10291133
10301134
@media (max-width: 600px) {
10311135
/* 标题适配 */
1032-
h1.text-h4 {
1136+
.page-title.text-h4 {
10331137
font-size: 1.5rem !important;
10341138
padding-top: 70px !important;
10351139
}
10361140
1037-
h2 {
1141+
.section-title {
10381142
font-size: 1.1rem !important;
10391143
}
10401144

0 commit comments

Comments
 (0)