Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ onMounted(async () => {
}

.code-fallback.dark-theme {
background-color: transparent;
background-color: #1e1e2e;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

为了保持主题一致性和可维护性,建议将硬编码的颜色值 #1e1e2e 替换为 Vuetify 主题变量。例如 rgb(var(--v-theme-surface))

如果这个颜色在多处使用且与现有主题变量都不同,最好在 src/theme/DarkTheme.ts 中将其定义为一个新的颜色变量,然后在所有使用到的地方统一调用。

此建议同样适用于第 181 行。

    background-color: rgb(var(--v-theme-surface));

}

.result-section {
Expand Down Expand Up @@ -178,7 +178,7 @@ onMounted(async () => {
}

.result-content.dark-theme {
background-color: transparent;
background-color: #1e1e2e;
}

.animate-fade-in {
Expand Down
14 changes: 7 additions & 7 deletions dashboard/src/components/shared/ConsoleDisplayer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ export default {
return {
autoScroll: true,
logColorAnsiMap: {
'\u001b[1;34m': 'color: #39C5BB; font-weight: bold;',
'\u001b[1;36m': 'color: #00FFFF; font-weight: bold;',
'\u001b[1;33m': 'color: #FFFF00; font-weight: bold;',
'\u001b[31m': 'color: #FF0000;',
'\u001b[1;31m': 'color: #FF0000; font-weight: bold;',
'\u001b[1;34m': 'color: #6cb6d9; font-weight: bold;',
'\u001b[1;36m': 'color: #72c4cc; font-weight: bold;',
'\u001b[1;33m': 'color: #d4b95e; font-weight: bold;',
'\u001b[31m': 'color: #d46a6a;',
'\u001b[1;31m': 'color: #e06060; font-weight: bold;',
'\u001b[0m': 'color: inherit; font-weight: normal;',
'\u001b[32m': 'color: #00FF00;',
'default': 'color: #FFFFFF;'
'\u001b[32m': 'color: #6cc070;',
'default': 'color: #c8c8c8;'
},
logLevels: ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
selectedLevels: [0, 1, 2, 3, 4],
Expand Down
6 changes: 4 additions & 2 deletions dashboard/src/components/shared/ExtensionCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,13 @@ const viewChangelog = () => {
? marketMode
? '#f8f0dd'
: '#ffffff'
: '#282833',
: marketMode
? '#3a3425'
: '#282833',
color:
useCustomizerStore().uiTheme === 'PurpleTheme'
? '#000000dd'
: '#ffffff',
: '#ffffffdd',
}"
>
<v-card-text
Expand Down
2 changes: 1 addition & 1 deletion dashboard/src/components/shared/ReadmeDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import MarkdownIt from "markdown-it";
import hljs from "highlight.js";
import axios from "axios";
import DOMPurify from "dompurify";
import "highlight.js/styles/github-dark.css";
import "highlight.js/styles/github.css";
import { useI18n } from "@/i18n/composables";

// 1. 在 setup 作用域创建 MarkdownIt 实例
Expand Down
4 changes: 4 additions & 0 deletions dashboard/src/components/shared/T2ITemplateEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,10 @@ defineExpose({
position: relative;
}

.v-theme--PurpleThemeDark .preview-container {
background-color: #1e1e2e;
}

.preview-container::before {
content: '';
position: absolute;
Expand Down
7 changes: 5 additions & 2 deletions dashboard/src/layouts/full/vertical-header/VerticalHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,7 @@ const isChristmas = computed(() => {
});

// 语言切换相关
const mainMenuOpen = ref(false);
const { languageOptions, currentLanguage, switchLanguage, locale } = useLanguageSwitcher();
const languages = computed(() =>
languageOptions.value.map(lang => ({
Expand All @@ -499,6 +500,7 @@ const languages = computed(() =>
const currentLocale = computed(() => locale.value);
const changeLanguage = async (langCode: string) => {
await switchLanguage(langCode as Locale);
mainMenuOpen.value = false;
};

onMounted(async () => {
Expand Down Expand Up @@ -591,7 +593,7 @@ onMounted(async () => {


<!-- 功能菜单 -->
<StyledMenu offset="12" location="bottom end">
<StyledMenu v-model="mainMenuOpen" offset="12" location="bottom end">
<template v-slot:activator="{ props: activatorProps }">
<v-btn
v-bind="activatorProps"
Expand Down Expand Up @@ -632,8 +634,8 @@ onMounted(async () => {

<!-- 语言切换分组 -->
<v-menu
open-on-click
:open-on-hover="!$vuetify.display.xs"
:open-on-click="$vuetify.display.xs"
:open-delay="!$vuetify.display.xs ? 60 : 0"
:close-delay="!$vuetify.display.xs ? 120 : 0"
:location="$vuetify.display.xs ? 'bottom' : 'start center'"
Expand All @@ -642,6 +644,7 @@ onMounted(async () => {
<template v-slot:activator="{ props: languageMenuProps }">
<v-list-item
v-bind="languageMenuProps"
@click.stop
class="styled-menu-item language-group-trigger"
rounded="md"
>
Expand Down
76 changes: 38 additions & 38 deletions dashboard/src/layouts/full/vertical-sidebar/VerticalSidebar.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup>
import { ref, shallowRef, onMounted, onUnmounted, watch } from 'vue';
import { ref, shallowRef, computed, onMounted, onUnmounted, watch } from 'vue';
import { useCustomizerStore } from '../../../stores/customizer';
import { useI18n } from '@/i18n/composables';
import sidebarItems from './sidebarItem';
Expand Down Expand Up @@ -84,53 +84,54 @@ const minSidebarWidth = 200;
const maxSidebarWidth = 300;
const isResizing = ref(false);

const iframeStyle = ref({
position: 'fixed',
bottom: '16px',
right: '16px',
width: '490px',
height: '640px',
minWidth: '300px',
minHeight: '200px',
background: 'white',
resize: 'both',
overflow: 'auto',
zIndex: '10000000',
borderRadius: '12px',
boxShadow: '0px 4px 12px rgba(0, 0, 0, 0.1)',
});
const isDark = computed(() => customizer.uiTheme === 'PurpleThemeDark');

const isMobile = window.innerWidth < 768;
if (isMobile) {
customizer.Sidebar_drawer = false;
}

const dragPos = ref({ left: '', top: '' });

if (window.innerWidth < 768) {
iframeStyle.value = {
position: 'fixed',
top: '10%',
left: '0%',
width: '100%',
height: '80%',
const iframeStyle = computed(() => {
const base = isMobile
? { position: 'fixed', top: '10%', left: '0%', width: '100%', height: '80%', zIndex: '1002' }
: { position: 'fixed', bottom: '16px', right: '16px', width: '490px', height: '640px', zIndex: '10000000' };
const pos = dragPos.value.left ? { left: dragPos.value.left, top: dragPos.value.top, bottom: 'auto', right: 'auto' } : {};
return {
...base,
...pos,
minWidth: '300px',
minHeight: '200px',
background: 'white',
background: isDark.value ? '#1e1e2e' : 'white',
resize: 'both',
overflow: 'auto',
zIndex: '1002',
borderRadius: '12px',
boxShadow: '0px 4px 12px rgba(0, 0, 0, 0.1)',
boxShadow: isDark.value ? '0px 4px 16px rgba(0, 0, 0, 0.5)' : '0px 4px 12px rgba(0, 0, 0, 0.1)',
};
customizer.Sidebar_drawer = false;
}
});

const dragHeaderStyle = {
const iframeInnerStyle = computed(() => ({
width: '100%',
height: 'calc(100% - 66px)',
border: 'none',
borderBottomLeftRadius: '12px',
borderBottomRightRadius: '12px',
filter: isDark.value ? 'invert(0.88) hue-rotate(180deg)' : 'none',
}));

const dragHeaderStyle = computed(() => ({
width: '100%',
padding: '8px',
background: '#f0f0f0',
borderBottom: '1px solid #ccc',
background: isDark.value ? '#2a2a3a' : '#f0f0f0',
borderBottom: isDark.value ? '1px solid #444' : '1px solid #ccc',
borderTopLeftRadius: '8px',
borderTopRightRadius: '8px',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
cursor: 'move'
};
}));

function toggleIframe() {
showIframe.value = !showIframe.value;
Expand Down Expand Up @@ -208,9 +209,8 @@ function moveAt(clientX, clientY) {
const dm = document.getElementById('draggable-iframe');
const newLeft = clamp(clientX - offsetX, 0, window.innerWidth - dm.offsetWidth);
const newTop = clamp(clientY - offsetY, 0, window.innerHeight - dm.offsetHeight);
// 将拖拽后的位置同步到响应式样式变量中
iframeStyle.value.left = newLeft + 'px';
iframeStyle.value.top = newTop + 'px';
// Sync dragged position to reactive variable
dragPos.value = { left: newLeft + 'px', top: newTop + 'px' };
}

function endDrag() {
Expand Down Expand Up @@ -348,23 +348,23 @@ function openChangelogDialog() {
icon
@click.stop="openIframeLink('https://astrbot.app')"
@mousedown.stop
style="border-radius: 8px; border: 1px solid #ccc;"
:style="{ borderRadius: '8px', border: isDark ? '1px solid #444' : '1px solid #ccc' }"
>
<v-icon icon="mdi-open-in-new" />
</v-btn>
<v-btn
icon
@click.stop="toggleIframe"
@mousedown.stop
style="border-radius: 8px; border: 1px solid #ccc;"
:style="{ borderRadius: '8px', border: isDark ? '1px solid #444' : '1px solid #ccc' }"
>
<v-icon icon="mdi-close" />
</v-btn>
</div>
</div>
<iframe
src="https://astrbot.app"
style="width: 100%; height: calc(100% - 66px); border: none; border-bottom-left-radius: 12px; border-bottom-right-radius: 12px;"
:style="iframeInnerStyle"
></iframe>
</div>

Expand Down
25 changes: 25 additions & 0 deletions dashboard/src/scss/_override.scss
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,29 @@ pre, code, .markdown pre, .markdown code, .release-notes pre, .release-notes cod
color: var(--astrbot-code-color);
}

// Dark mode global overrides
.v-theme--PurpleThemeDark {
// Override code text color for dark mode
--astrbot-code-color: #e0e0e0;

// Soften flat primary buttons for dark mode
.v-btn--variant-flat.bg-primary {
background-color: rgba(var(--v-theme-primary), 0.85) !important;
}

// Timeline dots: use a muted version
.v-timeline-item .v-timeline-divider__dot .v-timeline-divider__inner-dot {
opacity: 0.85;
}

// Ensure dialog/card surfaces use the dark surface color
.v-overlay__content > .v-card {
background-color: rgb(var(--v-theme-surface)) !important;
}

// Links inside markdown - slightly muted
.markdown-content a,
.markstream-vue a {
color: #6cb6ff;
}
}
107 changes: 107 additions & 0 deletions dashboard/src/scss/components/_HljsDark.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// highlight.js dark mode overrides
// Scoped to the dark Vuetify theme so the default github.css light styles work in light mode.
.v-theme--PurpleThemeDark {
.hljs {
background: transparent;
color: #adbac7;
}

.hljs-doctag,
.hljs-keyword,
.hljs-meta .hljs-keyword,
.hljs-template-tag,
.hljs-template-variable,
.hljs-type,
.hljs-variable.language_ {
color: #f47067;
}

.hljs-title,
.hljs-title.class_,
.hljs-title.class_.inherited__,
.hljs-title.function_ {
color: #dcbdfb;
}

.hljs-attr,
.hljs-attribute,
.hljs-literal,
.hljs-meta,
.hljs-number,
.hljs-operator,
.hljs-selector-attr,
.hljs-selector-class,
.hljs-selector-id,
.hljs-variable {
color: #6cb6ff;
}

.hljs-meta .hljs-string,
.hljs-regexp,
.hljs-string {
color: #96d0ff;
}

.hljs-built_in,
.hljs-symbol {
color: #f69d50;
}

.hljs-code,
.hljs-comment,
.hljs-formula {
color: #768390;
}

.hljs-name,
.hljs-quote,
.hljs-selector-pseudo,
.hljs-selector-tag {
color: #8ddb8c;
}

.hljs-subst {
color: #adbac7;
}

.hljs-section {
color: #316dca;
font-weight: bold;
}

.hljs-bullet {
color: #eac55f;
}

.hljs-emphasis {
color: #adbac7;
font-style: italic;
}

.hljs-strong {
color: #adbac7;
font-weight: bold;
}

.hljs-addition {
color: #b4f1b4;
background-color: #1b4721;
}

.hljs-deletion {
color: #ffd8d3;
background-color: #78191b;
}

// markstream-vue dark mode variables override
// markstream-vue expects a `.dark` ancestor to activate its dark palette,
// but Vuetify uses `.v-theme--PurpleThemeDark` instead.
.markstream-vue {
--border: 217.2 32.6% 17.5%;
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
--secondary: 217.2 32.6% 17.5%;
--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;
}
}
1 change: 1 addition & 0 deletions dashboard/src/scss/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
@import './components/VTextField';
@import './components/VTabs';
@import './components/VScrollbar';
@import './components/HljsDark';

@import './pages/dashboards';

Expand Down
Loading
Loading