mirror of
https://github.com/hellodigua/ChatLab.git
synced 2026-10-26 02:04:37 +08:00
feat(insight): add customizable report card themes
Give color-only theme controls localized positional labels and expose their selected state without adding visible scheme names.
This commit is contained in:
1 parent
25071890b2
commit
11eef47a7e
8 files changed
+136
-11
No files matched your search
@@ -1,10 +1,41 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useSettingsStore } from '@/stores/settings'
|
||||
import { getInsightCardTheme } from '@/utils/insight-card-theme'
|
||||
|
||||
const settingsStore = useSettingsStore()
|
||||
|
||||
const decorationStyle = computed(() => {
|
||||
const theme = getInsightCardTheme(settingsStore.insightCardTheme)
|
||||
|
||||
return {
|
||||
'--insight-card-glow-start': theme.startColor,
|
||||
'--insight-card-glow-end': theme.endColor,
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="pointer-events-none absolute inset-0 overflow-hidden">
|
||||
<div
|
||||
class="absolute -left-[20%] -top-[20%] h-[70%] w-[70%] rounded-full bg-blue-400/10 blur-[80px] dark:bg-blue-500/20"
|
||||
/>
|
||||
<div
|
||||
class="absolute -right-[20%] top-[10%] h-[70%] w-[70%] rounded-full bg-pink-400/10 blur-[80px] dark:bg-pink-500/20"
|
||||
/>
|
||||
<div class="pointer-events-none absolute inset-0 overflow-hidden" :style="decorationStyle">
|
||||
<div class="insight-card-glow-start absolute -left-[20%] -top-[20%] h-[70%] w-[70%] rounded-full blur-[80px]" />
|
||||
<div class="insight-card-glow-end absolute -right-[20%] top-[10%] h-[70%] w-[70%] rounded-full blur-[80px]" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.insight-card-glow-start {
|
||||
background-color: color-mix(in srgb, var(--insight-card-glow-start) 10%, transparent);
|
||||
}
|
||||
|
||||
.insight-card-glow-end {
|
||||
background-color: color-mix(in srgb, var(--insight-card-glow-end) 10%, transparent);
|
||||
}
|
||||
|
||||
:global(.dark) .insight-card-glow-start {
|
||||
background-color: color-mix(in srgb, var(--insight-card-glow-start) 20%, transparent);
|
||||
}
|
||||
|
||||
:global(.dark) .insight-card-glow-end {
|
||||
background-color: color-mix(in srgb, var(--insight-card-glow-end) 20%, transparent);
|
||||
}
|
||||
</style>
|
||||
@@ -10,6 +10,7 @@ import NetworkSettingsSection from './NetworkSettingsSection.vue'
|
||||
import UITabs from '@/components/UI/Tabs.vue'
|
||||
import { usePlatformService } from '@/services'
|
||||
import { IS_ELECTRON } from '@/utils/platform'
|
||||
import { INSIGHT_CARD_THEMES, type InsightCardThemeId } from '@/utils/insight-card-theme'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
@@ -17,7 +18,7 @@ const { t } = useI18n()
|
||||
const layoutStore = useLayoutStore()
|
||||
const settingsStore = useSettingsStore()
|
||||
const { toolsPanelPosition } = storeToRefs(layoutStore)
|
||||
const { locale, defaultSessionTab } = storeToRefs(settingsStore)
|
||||
const { locale, defaultSessionTab, insightCardTheme } = storeToRefs(settingsStore)
|
||||
|
||||
// Auto Launch
|
||||
const openAtLogin = ref(false)
|
||||
@@ -58,6 +59,16 @@ const colorModeOptions = computed(() => [
|
||||
{ label: t('settings.basic.appearance.dark'), value: 'dark' },
|
||||
])
|
||||
|
||||
function getInsightCardThemePreview(startColor: string, endColor: string) {
|
||||
return {
|
||||
background: `linear-gradient(135deg, color-mix(in srgb, ${startColor} 35%, white), color-mix(in srgb, ${endColor} 42%, white))`,
|
||||
}
|
||||
}
|
||||
|
||||
function selectInsightCardTheme(theme: InsightCardThemeId) {
|
||||
insightCardTheme.value = theme
|
||||
}
|
||||
|
||||
// Language options
|
||||
const languageOptions = computed(() =>
|
||||
availableLocales.map((l) => ({
|
||||
@@ -131,8 +142,8 @@ const toolsPanelPositionOptions = computed(() => [
|
||||
<UIcon name="i-heroicons-paint-brush" class="h-4 w-4 text-pink-500" />
|
||||
{{ t('settings.basic.appearance.title') }}
|
||||
</h3>
|
||||
<div class="rounded-lg border border-gray-200 bg-gray-50 p-4 dark:border-gray-700 dark:bg-gray-800/50">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="rounded-lg border border-gray-200 bg-gray-50 dark:border-gray-700 dark:bg-gray-800/50">
|
||||
<div class="flex items-center justify-between p-4">
|
||||
<div class="flex-1 pr-4">
|
||||
<p class="text-sm font-medium text-gray-900 dark:text-white">
|
||||
{{ t('settings.basic.appearance.themeMode') }}
|
||||
@@ -142,6 +153,42 @@ const toolsPanelPositionOptions = computed(() => [
|
||||
<UTabs v-model="colorMode" size="sm" class="gap-0" :items="colorModeOptions"></UTabs>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border-t border-gray-200 dark:border-gray-700"></div>
|
||||
<div class="flex items-center justify-between p-4">
|
||||
<div class="flex-1 pr-4">
|
||||
<p class="text-sm font-medium text-gray-900 dark:text-white">
|
||||
{{ t('settings.basic.appearance.insightCardTheme') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex shrink-0 items-center gap-1.5">
|
||||
<button
|
||||
v-for="(theme, index) in INSIGHT_CARD_THEMES"
|
||||
:key="theme.id"
|
||||
type="button"
|
||||
class="group flex h-9 w-9 items-center justify-center rounded-full outline-none transition-colors hover:bg-gray-200/60 focus-visible:ring-2 focus-visible:ring-primary-500/40 dark:hover:bg-gray-700/70"
|
||||
:aria-label="t('settings.basic.appearance.insightCardThemeOption', { index: index + 1 })"
|
||||
:aria-pressed="insightCardTheme === theme.id"
|
||||
@click="selectInsightCardTheme(theme.id)"
|
||||
>
|
||||
<span
|
||||
class="relative block h-6 w-6 overflow-hidden rounded-full shadow-sm ring-1 transition-all"
|
||||
:class="
|
||||
insightCardTheme === theme.id
|
||||
? 'ring-2 ring-primary-500 ring-offset-2 ring-offset-gray-50 dark:ring-primary-400 dark:ring-offset-gray-800'
|
||||
: 'ring-black/5 group-hover:ring-black/10 dark:ring-white/10 dark:group-hover:ring-white/20'
|
||||
"
|
||||
:style="getInsightCardThemePreview(theme.startColor, theme.endColor)"
|
||||
>
|
||||
<span
|
||||
v-if="insightCardTheme === theme.id"
|
||||
class="absolute inset-0 flex items-center justify-center text-gray-800/70"
|
||||
>
|
||||
<UIcon name="i-heroicons-check-20-solid" class="h-3.5 w-3.5" />
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
"appearance": {
|
||||
"title": "Appearance",
|
||||
"themeMode": "Theme Mode",
|
||||
"insightCardTheme": "Insight card colors",
|
||||
"insightCardThemeOption": "Color scheme {index}",
|
||||
"auto": "System",
|
||||
"light": "Light",
|
||||
"dark": "Dark"
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
"appearance": {
|
||||
"title": "外観設定",
|
||||
"themeMode": "テーマモード",
|
||||
"insightCardTheme": "インサイトカードの配色",
|
||||
"insightCardThemeOption": "配色 {index}",
|
||||
"auto": "システムに従う",
|
||||
"light": "ライトモード",
|
||||
"dark": "ダークモード"
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
"appearance": {
|
||||
"title": "外观设置",
|
||||
"themeMode": "主题模式",
|
||||
"insightCardTheme": "洞察卡片配色",
|
||||
"insightCardThemeOption": "配色 {index}",
|
||||
"auto": "跟随系统",
|
||||
"light": "浅色模式",
|
||||
"dark": "深色模式"
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
"appearance": {
|
||||
"title": "外觀設定",
|
||||
"themeMode": "主題模式",
|
||||
"insightCardTheme": "洞察卡片配色",
|
||||
"insightCardThemeOption": "配色 {index}",
|
||||
"auto": "依系統設定",
|
||||
"light": "淺色模式",
|
||||
"dark": "深色模式"
|
||||
|
||||
@@ -10,6 +10,7 @@ import type { PreprocessConfig } from '@electron/preload/index'
|
||||
import type { AIPreprocessConfig } from '@openchatlab/shared-types'
|
||||
import { useAIService, usePlatformService } from '@/services'
|
||||
import { PLATFORM_CAPABILITIES } from '@/utils/platform-capabilities'
|
||||
import { DEFAULT_INSIGHT_CARD_THEME, type InsightCardThemeId } from '@/utils/insight-card-theme'
|
||||
|
||||
const DESENSITIZE_RULES_SCHEMA_VERSION = 2
|
||||
|
||||
@@ -35,6 +36,8 @@ export const useSettingsStore = defineStore(
|
||||
|
||||
const defaultSessionTab = ref<'insights' | 'ai-chat'>('insights')
|
||||
|
||||
const insightCardTheme = ref<InsightCardThemeId>(DEFAULT_INSIGHT_CARD_THEME)
|
||||
|
||||
const debugMode = ref(false)
|
||||
|
||||
function setDebugMode(enabled: boolean) {
|
||||
@@ -112,6 +115,7 @@ export const useSettingsStore = defineStore(
|
||||
setLocale,
|
||||
initLocale,
|
||||
defaultSessionTab,
|
||||
insightCardTheme,
|
||||
debugMode,
|
||||
setDebugMode,
|
||||
aiPreprocessConfig,
|
||||
@@ -120,7 +124,7 @@ export const useSettingsStore = defineStore(
|
||||
},
|
||||
{
|
||||
persist: {
|
||||
pick: ['debugMode'],
|
||||
pick: ['debugMode', 'insightCardTheme'],
|
||||
storage: localStorage,
|
||||
},
|
||||
backendPersist: {
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
export const INSIGHT_CARD_THEME_IDS = [
|
||||
'default',
|
||||
'sunset',
|
||||
'galaxy',
|
||||
'mist',
|
||||
'moonlight',
|
||||
'berry',
|
||||
'sunshine',
|
||||
'aurora',
|
||||
] as const
|
||||
|
||||
export type InsightCardThemeId = (typeof INSIGHT_CARD_THEME_IDS)[number]
|
||||
|
||||
export interface InsightCardTheme {
|
||||
id: InsightCardThemeId
|
||||
startColor: string
|
||||
endColor: string
|
||||
}
|
||||
|
||||
export const DEFAULT_INSIGHT_CARD_THEME: InsightCardThemeId = 'default'
|
||||
|
||||
export const INSIGHT_CARD_THEMES: readonly InsightCardTheme[] = [
|
||||
{ id: 'default', startColor: '#60a5fa', endColor: '#f472b6' },
|
||||
{ id: 'sunset', startColor: '#fb923c', endColor: '#fb7185' },
|
||||
{ id: 'galaxy', startColor: '#818cf8', endColor: '#c084fc' },
|
||||
{ id: 'mist', startColor: '#22d3ee', endColor: '#60a5fa' },
|
||||
{ id: 'moonlight', startColor: '#22c55e', endColor: '#14b8a6' },
|
||||
{ id: 'berry', startColor: '#fb7185', endColor: '#a78bfa' },
|
||||
{ id: 'sunshine', startColor: '#f59e0b', endColor: '#facc15' },
|
||||
{ id: 'aurora', startColor: '#34d399', endColor: '#818cf8' },
|
||||
]
|
||||
|
||||
export function getInsightCardTheme(id: InsightCardThemeId): InsightCardTheme {
|
||||
return INSIGHT_CARD_THEMES.find((theme) => theme.id === id) ?? INSIGHT_CARD_THEMES[0]
|
||||
}
|
||||
Reference in new issue
Block a user