feat: add dark/light theme

This commit is contained in:
engigu
2025-09-30 22:24:29 +08:00
parent f3f378115d
commit 415bed6093
11 changed files with 175 additions and 56 deletions
@@ -161,7 +161,7 @@ onMounted(async () => {
<div class="flex-shrink-0">
<Dialog v-model:open="isAddCronMessageDialogOpen">
<DialogTrigger as-child>
<Button variant="default" class="w-full sm:w-auto bg-gray-800 hover:bg-gray-900">
<Button variant="default" class="w-full sm:w-auto">
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
</svg>
@@ -212,7 +212,9 @@ onMounted(async () => {
<TableCell class="max-w-32 truncate" :title="cronMessage.title">{{ cronMessage.title }}</TableCell>
<TableCell class="max-w-32 truncate" :title="cronMessage.content">{{ cronMessage.content }}</TableCell>
<TableCell>
<code class="bg-gray-100 px-2 py-1 rounded text-sm">{{ cronMessage.cron }}</code>
<code class="px-2 py-1 rounded text-sm font-mono bg-muted text-foreground border border-border">
{{ cronMessage.cron }}
</code>
</TableCell>
<TableCell class="max-w-24 truncate" :title="cronMessage.task_id">{{ cronMessage.task_id }}</TableCell>
<TableCell class="max-w-32 truncate" :title="cronMessage.next_time || '-'">{{ cronMessage.next_time || '-' }}
@@ -256,7 +256,7 @@ const renderLineChart = () => {
enabled: true,
shared: true,
intersect: false,
theme: 'light',
theme: document.documentElement.classList.contains('dark') ? 'dark' : 'light',
style: {
fontSize: '12px',
fontFamily: 'Inter, sans-serif'
@@ -279,28 +279,33 @@ const renderLineChart = () => {
const total = successCount + failedCount;
const successRate = total > 0 ? ((successCount / total) * 100).toFixed(1) : '0.0';
const containerCls = 'bg-card text-foreground p-3 rounded-lg shadow-lg border border-border';
const labelMutedCls = 'text-sm text-muted-foreground';
const valueStrongCls = 'text-sm font-medium text-foreground';
const successRateCls = 'text-sm font-medium';
return `
<div class="bg-white p-3 rounded-lg shadow-lg border">
<div class="font-medium text-gray-900 mb-2">${w.globals.categoryLabels[dataPointIndex]}</div>
<div class="${containerCls}">
<div class="font-medium mb-2">${w.globals.categoryLabels[dataPointIndex]}</div>
<div class="space-y-1">
<div class="flex items-center justify-between">
<span class="flex items-center">
<span class="w-2 h-2 bg-green-500 rounded-full mr-2"></span>
<span class="text-sm text-gray-600">成功:</span>
<span class="${labelMutedCls}">成功:</span>
</span>
<span class="text-sm font-medium text-gray-900">${successCount} 条</span>
<span class="${valueStrongCls}">${successCount} 条</span>
</div>
<div class="flex items-center justify-between">
<span class="flex items-center">
<span class="w-2 h-2 bg-red-500 rounded-full mr-2"></span>
<span class="text-sm text-gray-600">失败:</span>
<span class="${labelMutedCls}">失败:</span>
</span>
<span class="text-sm font-medium text-gray-900">${failedCount} 条</span>
<span class="${valueStrongCls}">${failedCount} 条</span>
</div>
<div class="border-t pt-1 mt-2">
<div class="border-t border-border pt-1 mt-2">
<div class="flex items-center justify-between">
<span class="text-sm text-gray-600">成功率:</span>
<span class="text-sm font-medium text-green-600">${successRate}%</span>
<span class="${labelMutedCls}">成功率:</span>
<span class="${successRateCls}">${successRate}%</span>
</div>
</div>
</div>
@@ -165,8 +165,8 @@ onMounted(async () => {
<SheetTitle>{{ selectedTaskName }} - 托管消息详情</SheetTitle>
</SheetHeader>
<div class="mt-4">
<div class="bg-gray-50 p-4 rounded-lg max-h-[82vh] overflow-y-auto break-words">
<pre class="whitespace-pre-wrap text-sm font-mono">{{ selectedLog }}</pre>
<div class="bg-card p-4 rounded-lg border border-border max-h-[82vh] overflow-y-auto break-words">
<pre class="whitespace-pre-wrap text-sm font-mono text-foreground">{{ selectedLog }}</pre>
</div>
</div>
</SheetContent>
@@ -240,8 +240,8 @@ onMounted(async () => {
<SheetTitle>{{ selectedTaskName }} - 发信日志详情</SheetTitle>
</SheetHeader>
<div class="mt-4">
<div class="bg-gray-50 p-4 rounded-lg max-h-[82vh] overflow-y-auto break-words">
<pre class="whitespace-pre-wrap text-sm font-mono">{{ selectedLog }}</pre>
<div class="bg-card p-4 rounded-lg border border-border max-h-[82vh] overflow-y-auto break-words">
<pre class="whitespace-pre-wrap text-sm font-mono text-foreground">{{ selectedLog }}</pre>
</div>
</div>
</SheetContent>
@@ -177,7 +177,7 @@ onMounted(async () => {
<div class="flex-shrink-0">
<Dialog v-model:open="isAddChannelDrawerOpen">
<DialogTrigger as-child>
<Button variant="default" class="w-full sm:w-auto bg-gray-800 hover:bg-gray-900">
<Button variant="default" class="w-full sm:w-auto">
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
</svg>
@@ -265,8 +265,8 @@ onMounted(async () => {
<SheetTitle>{{ selectedChannelName }} - 发信方式配置详情</SheetTitle>
</SheetHeader>
<div class="mt-6">
<div class="bg-gray-50 p-4 rounded-lg">
<pre class="whitespace-pre-wrap text-sm font-mono">{{ selectedConfig }}</pre>
<div class="bg-card p-4 rounded-lg border border-border">
<pre class="whitespace-pre-wrap text-sm font-mono text-foreground">{{ selectedConfig }}</pre>
</div>
</div>
</SheetContent>
@@ -186,7 +186,7 @@ onMounted(async () => {
<div class="flex-shrink-0">
<Drawer v-model:open="isAddChannelDrawerOpen">
<DrawerTrigger as-child>
<Button variant="default" class="w-full sm:w-auto bg-gray-800 hover:bg-gray-900">
<Button variant="default" class="w-full sm:w-auto">
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
</svg>
@@ -275,8 +275,8 @@ onMounted(async () => {
<SheetTitle>{{ selectedChannelName }} - 发信方式配置详情</SheetTitle>
</SheetHeader>
<div class="mt-6">
<div class="bg-gray-50 p-4 rounded-lg">
<pre class="whitespace-pre-wrap text-sm font-mono">{{ selectedConfig }}</pre>
<div class="bg-card p-4 rounded-lg border border-border">
<pre class="whitespace-pre-wrap text-sm font-mono text-foreground">{{ selectedConfig }}</pre>
</div>
</div>
</SheetContent>
@@ -44,10 +44,10 @@ export default {
:key="item.id"
@click="$emit('update:activeTab', item.id)"
:class="[
'w-full flex items-center px-4 py-3 text-left text-sm font-medium transition-colors',
'w-full flex items-center px-4 py-3 text-left text-sm font-medium transition-colors rounded-md',
activeTab === item.id
? 'bg-blue-50 text-blue-700 border-r-2 border-blue-700'
: 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'
? 'bg-accent text-accent-foreground border-r-2 border-primary dark:bg-accent/40'
: 'text-muted-foreground hover:bg-muted hover:text-foreground dark:hover:bg-white/5'
]"
>
<component :is="item.icon" class="mr-3 w-5 h-5" />
@@ -111,9 +111,9 @@ export default {
<label class="text-sm font-medium text-gray-700">站点图标(只支持svg文本)</label>
<Input v-model="state.logo" placeholder="请输入自定义的网站logosvg文本)" />
<!-- SVG预览 -->
<div v-if="state.logo" class="mt-2 p-3 border border-gray-200 rounded-md bg-gray-50">
<div class="text-xs text-gray-500 mb-2">预览效果</div>
<div class="flex items-center justify-center w-16 h-16 bg-white border border-gray-300 rounded"
<div v-if="state.logo" class="mt-2 p-3 border border-border rounded-md bg-card">
<div class="text-xs text-muted-foreground mb-2">预览效果</div>
<div class="flex items-center justify-center w-16 h-16 bg-white dark:bg-white border border-border rounded"
v-html="state.logo"></div>
</div>
</div>