mirror of
https://github.com/SECTL/SecScore.git
synced 2026-07-19 19:04:23 +08:00
feat(主题): 添加自定义主题和Mica效果支持
实现自定义主题配置功能,支持设置Mica、Acrylic等窗口效果 添加多个预设主题配置文件 修改侧边栏样式以适配透明效果 扩展主题服务以处理自定义主题配置
This commit is contained in:
@@ -9,6 +9,11 @@ export interface themeConfig {
|
||||
name: string
|
||||
id: string
|
||||
mode: 'light' | 'dark'
|
||||
mica?: {
|
||||
effect: 'mica' | 'tabbed' | 'acrylic' | 'blur' | 'transparent' | 'none'
|
||||
theme: 'auto' | 'dark' | 'light'
|
||||
radius: 'small' | 'medium' | 'large'
|
||||
}
|
||||
config: {
|
||||
tdesign: Record<string, string>
|
||||
custom: Record<string, string>
|
||||
@@ -78,9 +83,56 @@ export class ThemeService extends Service {
|
||||
return { success: false, message: 'Permission denied' }
|
||||
}
|
||||
this.currentThemeId = themeId
|
||||
this.applyMicaEffect(themeId)
|
||||
this.notifyThemeUpdate()
|
||||
return { success: true }
|
||||
})
|
||||
|
||||
this.mainCtx.handle('theme:set-custom', async (event, config: {
|
||||
effect: 'mica' | 'tabbed' | 'acrylic' | 'blur' | 'transparent' | 'none'
|
||||
theme: 'auto' | 'dark' | 'light'
|
||||
radius: 'small' | 'medium' | 'large'
|
||||
}) => {
|
||||
if (!this.mainCtx.permissions.requirePermission(event, 'admin'))
|
||||
return { success: false, message: 'Permission denied' }
|
||||
|
||||
this.currentThemeId = 'custom'
|
||||
this.applyMicaConfig(config)
|
||||
this.notifyThemeUpdate()
|
||||
return { success: true }
|
||||
})
|
||||
}
|
||||
|
||||
private applyMicaEffect(themeId: string) {
|
||||
const theme = this.getThemeById(themeId)
|
||||
if (!theme?.mica) return
|
||||
|
||||
this.applyMicaConfig(theme.mica)
|
||||
}
|
||||
|
||||
private applyMicaConfig(config: {
|
||||
effect: 'mica' | 'tabbed' | 'acrylic' | 'blur' | 'transparent' | 'none'
|
||||
theme: 'auto' | 'dark' | 'light'
|
||||
radius: 'small' | 'medium' | 'large'
|
||||
}) {
|
||||
const radiusMap: Record<string, 'rounded' | 'small' | 'square'> = {
|
||||
'small': 'small',
|
||||
'medium': 'rounded',
|
||||
'large': 'rounded'
|
||||
}
|
||||
|
||||
const windows = BrowserWindow.getAllWindows()
|
||||
for (const win of windows) {
|
||||
if (win.isDestroyed()) continue
|
||||
|
||||
this.mainCtx.windows.setMicaEffect(win, config.effect)
|
||||
this.mainCtx.windows.setMicaTheme(win, config.theme)
|
||||
this.mainCtx.windows.setMicaCorner(win, radiusMap[config.radius] || 'rounded')
|
||||
}
|
||||
|
||||
this.mainCtx.settings.setValue('window_effect', config.effect)
|
||||
this.mainCtx.settings.setValue('window_theme', config.theme)
|
||||
this.mainCtx.settings.setValue('window_radius', radiusMap[config.radius] || 'rounded')
|
||||
}
|
||||
|
||||
private getThemeList(): themeConfig[] {
|
||||
|
||||
@@ -7,6 +7,11 @@ const api = {
|
||||
getThemes: () => ipcRenderer.invoke('theme:list'),
|
||||
getCurrentTheme: () => ipcRenderer.invoke('theme:current'),
|
||||
setTheme: (themeId: string) => ipcRenderer.invoke('theme:set', themeId),
|
||||
setCustomTheme: (config: {
|
||||
effect: 'mica' | 'tabbed' | 'acrylic' | 'blur' | 'transparent' | 'none'
|
||||
theme: 'auto' | 'dark' | 'light'
|
||||
radius: 'small' | 'medium' | 'large'
|
||||
}) => ipcRenderer.invoke('theme:set-custom', config),
|
||||
onThemeChanged: (callback: (theme: themeConfig) => void) => {
|
||||
const subscription = (_event: any, theme: themeConfig) => callback(theme)
|
||||
ipcRenderer.on('theme:updated', subscription)
|
||||
|
||||
@@ -11,6 +11,11 @@ export interface themeConfig {
|
||||
name: string
|
||||
id: string
|
||||
mode: 'light' | 'dark'
|
||||
mica?: {
|
||||
effect: 'mica' | 'tabbed' | 'acrylic' | 'blur' | 'transparent' | 'none'
|
||||
theme: 'auto' | 'dark' | 'light'
|
||||
radius: 'small' | 'medium' | 'large'
|
||||
}
|
||||
config: {
|
||||
tdesign: Record<string, string>
|
||||
custom: Record<string, string>
|
||||
@@ -38,6 +43,11 @@ export interface electronApi {
|
||||
getThemes: () => Promise<ipcResponse<themeConfig[]>>
|
||||
getCurrentTheme: () => Promise<ipcResponse<themeConfig>>
|
||||
setTheme: (themeId: string) => Promise<ipcResponse<void>>
|
||||
setCustomTheme: (config: {
|
||||
effect: 'mica' | 'tabbed' | 'acrylic' | 'blur' | 'transparent' | 'none'
|
||||
theme: 'auto' | 'dark' | 'light'
|
||||
radius: 'small' | 'medium' | 'large'
|
||||
}) => Promise<ipcResponse<void>>
|
||||
onThemeChanged: (callback: (theme: themeConfig) => void) => () => void
|
||||
|
||||
// DB - Student
|
||||
|
||||
@@ -99,10 +99,10 @@ html[theme-mode='dark'] .ss-sidebar .t-menu__item.t-is-active svg:not([fill='non
|
||||
|
||||
/* Global Sidebar Toggle Button */
|
||||
.global-sidebar-toggle {
|
||||
width: 24px;
|
||||
height: 60px;
|
||||
background-color: var(--ss-card-bg);
|
||||
border-radius: 8px 0 0 8px;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-color: var(--ss-bg-color);
|
||||
border-radius: 0px 0 0 0px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -126,7 +126,7 @@ html[theme-mode='dark'] .ss-sidebar .t-menu__item.t-is-active svg:not([fill='non
|
||||
.sidebar-content-area {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
backgroundColor: var(--ss-card-bg);
|
||||
background-color: var(--ss-card-bg);
|
||||
border-radius: 12px 0 0 12px;
|
||||
box-shadow: -4px 0 16px rgba(0,0,0,0.15);
|
||||
border: 1px solid var(--ss-border-color);
|
||||
|
||||
@@ -55,10 +55,11 @@ export const GlobalSidebar: React.FC = () => {
|
||||
// 1. 先隐藏三角
|
||||
setShowToggle(false)
|
||||
|
||||
|
||||
// 2. 稍后扩大窗口
|
||||
setTimeout(() => {
|
||||
if ((window as any).api) {
|
||||
const width = Math.round(84 * zoom)
|
||||
const width = Math.round(60 * zoom)
|
||||
const height = Math.round(300 * zoom)
|
||||
;(window as any).api.windowResize(width, height)
|
||||
}
|
||||
@@ -77,7 +78,7 @@ export const GlobalSidebar: React.FC = () => {
|
||||
setTimeout(() => {
|
||||
if ((window as any).api) {
|
||||
const width = Math.round(24 * zoom)
|
||||
const height = Math.round(300 * zoom)
|
||||
const height = Math.round(58 * zoom)
|
||||
;(window as any).api.windowResize(width, height)
|
||||
}
|
||||
// 3. 最后重新显示三角(等待透明度动画完成)
|
||||
@@ -99,7 +100,7 @@ export const GlobalSidebar: React.FC = () => {
|
||||
width: `84px`,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-end',
|
||||
justifyContent: 'flex-start',
|
||||
overflow: 'hidden',
|
||||
background: 'transparent'
|
||||
}}
|
||||
@@ -110,9 +111,10 @@ export const GlobalSidebar: React.FC = () => {
|
||||
className={`global-sidebar-toggle ${!showToggle ? 'hidden' : ''}`}
|
||||
style={{
|
||||
willChange: 'opacity, transform',
|
||||
width: `24px`,
|
||||
height: `60px`
|
||||
width: `${!expanded ? '100vw' : '0px'}`,
|
||||
height: `100vh`
|
||||
}}
|
||||
hidden={!expanded}
|
||||
>
|
||||
<ChevronLeftIcon />
|
||||
</div>
|
||||
@@ -121,11 +123,10 @@ export const GlobalSidebar: React.FC = () => {
|
||||
<div
|
||||
className={`sidebar-content-area ${expanded ? 'visible' : 'hidden'}`}
|
||||
style={{
|
||||
backgroundColor: 'var(--ss-card-bg)',
|
||||
backgroundColor: 'var(--ss-bg-color)',
|
||||
height: 'fit-content',
|
||||
willChange: 'opacity, transform',
|
||||
width: `60px`,
|
||||
padding: `12px 8px`,
|
||||
gap: `12px`
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "Acrylic-自动",
|
||||
"id": "acrylic-auto",
|
||||
"mode": "light",
|
||||
"mica": {
|
||||
"effect": "acrylic",
|
||||
"theme": "auto",
|
||||
"radius": "medium"
|
||||
},
|
||||
"config": {
|
||||
"tdesign": {
|
||||
"brandColor": "#0052D9",
|
||||
"warningColor": "#E37318",
|
||||
"errorColor": "#D32029",
|
||||
"successColor": "#248232"
|
||||
},
|
||||
"custom": {
|
||||
"--ss-bg-color": "transparent",
|
||||
"--ss-card-bg": "rgba(255, 255, 255, 0.85)",
|
||||
"--ss-text-main": "#1a1a1a",
|
||||
"--ss-text-secondary": "#5e5e5e",
|
||||
"--ss-border-color": "rgba(0, 0, 0, 0.08)",
|
||||
"--ss-header-bg": "transparent",
|
||||
"--ss-sidebar-bg": "rgba(255, 255, 255, 0.9)",
|
||||
"--ss-item-hover": "rgba(0, 0, 0, 0.04)",
|
||||
"--ss-sidebar-text": "#1a1a1a",
|
||||
"--ss-sidebar-active-bg": "rgba(0, 0, 0, 0.06)",
|
||||
"--ss-sidebar-active-text": "#1a1a1a"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "Acrylic-深色",
|
||||
"id": "acrylic-dark",
|
||||
"mode": "dark",
|
||||
"mica": {
|
||||
"effect": "acrylic",
|
||||
"theme": "dark",
|
||||
"radius": "medium"
|
||||
},
|
||||
"config": {
|
||||
"tdesign": {
|
||||
"brandColor": "#4C8BF5",
|
||||
"warningColor": "#E37318",
|
||||
"errorColor": "#D54941",
|
||||
"successColor": "#2BA471"
|
||||
},
|
||||
"custom": {
|
||||
"--ss-bg-color": "transparent",
|
||||
"--ss-card-bg": "rgba(30, 30, 30, 0.85)",
|
||||
"--ss-text-main": "#e0e0e0",
|
||||
"--ss-text-secondary": "#a0a0a0",
|
||||
"--ss-border-color": "rgba(255, 255, 255, 0.08)",
|
||||
"--ss-header-bg": "transparent",
|
||||
"--ss-sidebar-bg": "rgba(30, 30, 30, 0.9)",
|
||||
"--ss-item-hover": "rgba(255, 255, 255, 0.04)",
|
||||
"--ss-sidebar-text": "#e0e0e0",
|
||||
"--ss-sidebar-active-bg": "rgba(255, 255, 255, 0.06)",
|
||||
"--ss-sidebar-active-text": "#e0e0e0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "Acrylic-浅色",
|
||||
"id": "acrylic-light",
|
||||
"mode": "light",
|
||||
"mica": {
|
||||
"effect": "acrylic",
|
||||
"theme": "light",
|
||||
"radius": "medium"
|
||||
},
|
||||
"config": {
|
||||
"tdesign": {
|
||||
"brandColor": "#0052D9",
|
||||
"warningColor": "#E37318",
|
||||
"errorColor": "#D32029",
|
||||
"successColor": "#248232"
|
||||
},
|
||||
"custom": {
|
||||
"--ss-bg-color": "transparent",
|
||||
"--ss-card-bg": "rgba(255, 255, 255, 0.85)",
|
||||
"--ss-text-main": "#1a1a1a",
|
||||
"--ss-text-secondary": "#5e5e5e",
|
||||
"--ss-border-color": "rgba(0, 0, 0, 0.08)",
|
||||
"--ss-header-bg": "transparent",
|
||||
"--ss-sidebar-bg": "rgba(255, 255, 255, 0.9)",
|
||||
"--ss-item-hover": "rgba(0, 0, 0, 0.04)",
|
||||
"--ss-sidebar-text": "#1a1a1a",
|
||||
"--ss-sidebar-active-bg": "rgba(0, 0, 0, 0.06)",
|
||||
"--ss-sidebar-active-text": "#1a1a1a"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "自定义",
|
||||
"id": "custom",
|
||||
"mode": "light",
|
||||
"mica": {
|
||||
"effect": "mica",
|
||||
"theme": "auto",
|
||||
"radius": "medium"
|
||||
},
|
||||
"config": {
|
||||
"tdesign": {
|
||||
"brandColor": "#0052D9",
|
||||
"warningColor": "#E37318",
|
||||
"errorColor": "#D32029",
|
||||
"successColor": "#248232"
|
||||
},
|
||||
"custom": {
|
||||
"--ss-bg-color": "transparent",
|
||||
"--ss-card-bg": "rgba(255, 255, 255, 0.7)",
|
||||
"--ss-text-main": "#1a1a1a",
|
||||
"--ss-text-secondary": "#5e5e5e",
|
||||
"--ss-border-color": "rgba(0, 0, 0, 0.1)",
|
||||
"--ss-header-bg": "transparent",
|
||||
"--ss-sidebar-bg": "rgba(255, 255, 255, 0.85)",
|
||||
"--ss-item-hover": "rgba(0, 0, 0, 0.05)",
|
||||
"--ss-sidebar-text": "#1a1a1a",
|
||||
"--ss-sidebar-active-bg": "rgba(0, 0, 0, 0.08)",
|
||||
"--ss-sidebar-active-text": "#1a1a1a"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "Mica-自动",
|
||||
"id": "mica-auto",
|
||||
"mode": "light",
|
||||
"mica": {
|
||||
"effect": "mica",
|
||||
"theme": "auto",
|
||||
"radius": "medium"
|
||||
},
|
||||
"config": {
|
||||
"tdesign": {
|
||||
"brandColor": "#0052D9",
|
||||
"warningColor": "#E37318",
|
||||
"errorColor": "#D32029",
|
||||
"successColor": "#248232"
|
||||
},
|
||||
"custom": {
|
||||
"--ss-bg-color": "transparent",
|
||||
"--ss-card-bg": "rgba(255, 255, 255, 0.7)",
|
||||
"--ss-text-main": "#1a1a1a",
|
||||
"--ss-text-secondary": "#5e5e5e",
|
||||
"--ss-border-color": "rgba(0, 0, 0, 0.1)",
|
||||
"--ss-header-bg": "transparent",
|
||||
"--ss-sidebar-bg": "rgba(255, 255, 255, 0.85)",
|
||||
"--ss-item-hover": "rgba(0, 0, 0, 0.05)",
|
||||
"--ss-sidebar-text": "#1a1a1a",
|
||||
"--ss-sidebar-active-bg": "rgba(0, 0, 0, 0.08)",
|
||||
"--ss-sidebar-active-text": "#1a1a1a"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "Mica-深色",
|
||||
"id": "mica-dark",
|
||||
"mode": "dark",
|
||||
"mica": {
|
||||
"effect": "mica",
|
||||
"theme": "dark",
|
||||
"radius": "medium"
|
||||
},
|
||||
"config": {
|
||||
"tdesign": {
|
||||
"brandColor": "#4C8BF5",
|
||||
"warningColor": "#E37318",
|
||||
"errorColor": "#D54941",
|
||||
"successColor": "#2BA471"
|
||||
},
|
||||
"custom": {
|
||||
"--ss-bg-color": "transparent",
|
||||
"--ss-card-bg": "rgba(30, 30, 30, 0.7)",
|
||||
"--ss-text-main": "#e0e0e0",
|
||||
"--ss-text-secondary": "#a0a0a0",
|
||||
"--ss-border-color": "rgba(255, 255, 255, 0.1)",
|
||||
"--ss-header-bg": "transparent",
|
||||
"--ss-sidebar-bg": "rgba(30, 30, 30, 0.85)",
|
||||
"--ss-item-hover": "rgba(255, 255, 255, 0.05)",
|
||||
"--ss-sidebar-text": "#e0e0e0",
|
||||
"--ss-sidebar-active-bg": "rgba(255, 255, 255, 0.08)",
|
||||
"--ss-sidebar-active-text": "#e0e0e0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "Mica-浅色",
|
||||
"id": "mica-light",
|
||||
"mode": "light",
|
||||
"mica": {
|
||||
"effect": "mica",
|
||||
"theme": "light",
|
||||
"radius": "medium"
|
||||
},
|
||||
"config": {
|
||||
"tdesign": {
|
||||
"brandColor": "#0052D9",
|
||||
"warningColor": "#E37318",
|
||||
"errorColor": "#D32029",
|
||||
"successColor": "#248232"
|
||||
},
|
||||
"custom": {
|
||||
"--ss-bg-color": "transparent",
|
||||
"--ss-card-bg": "rgba(255, 255, 255, 0.7)",
|
||||
"--ss-text-main": "#1a1a1a",
|
||||
"--ss-text-secondary": "#5e5e5e",
|
||||
"--ss-border-color": "rgba(0, 0, 0, 0.1)",
|
||||
"--ss-header-bg": "transparent",
|
||||
"--ss-sidebar-bg": "rgba(255, 255, 255, 0.85)",
|
||||
"--ss-item-hover": "rgba(0, 0, 0, 0.05)",
|
||||
"--ss-sidebar-text": "#1a1a1a",
|
||||
"--ss-sidebar-active-bg": "rgba(0, 0, 0, 0.08)",
|
||||
"--ss-sidebar-active-text": "#1a1a1a"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user