feat(theme): 添加暗色主题支持

- 新增暗色主题选项和系统主题自动适配功能
- 调整了部分样式以适应暗色主题
This commit is contained in:
himeditator
2025-07-05 00:54:12 +08:00
parent 14e7a7bce4
commit f29e15cde5
20 changed files with 192 additions and 46 deletions

View File

@@ -4,16 +4,20 @@
<script setup lang="ts">
import { onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { FullConfig } from './types'
import { useCaptionLogStore } from './stores/captionLog'
import { useCaptionStyleStore } from './stores/captionStyle'
import { useEngineControlStore } from './stores/engineControl'
import { useGeneralSettingStore } from './stores/generalSetting'
const router = useRouter()
onMounted(() => {
console.log('Current route:', router.currentRoute.value.fullPath)
window.electron.ipcRenderer.invoke('both.window.mounted').then((data: FullConfig) => {
console.log(data)
useGeneralSettingStore().uiLanguage = data.uiLanguage
useGeneralSettingStore().uiTheme = data.uiTheme
useGeneralSettingStore().leftBarWidth = data.leftBarWidth
useCaptionStyleStore().setStyles(data.styles)
useEngineControlStore().setControls(data.controls)

View File

@@ -1,3 +1,10 @@
/* :root {
:root {
--control-background: #fff;
}
} */
body {
margin: 0;
padding: 0;
height: 100vh;
overflow: hidden;
}

View File

@@ -1,6 +0,0 @@
body {
margin: 0;
padding: 0;
height: 100vh;
overflow: hidden;
}

View File

@@ -1,7 +1,9 @@
<template>
<div class="caption-list">
<div class="caption-title">
<span style="margin-right: 30px;">{{ $t('log.title') }}</span>
<div>
<a-app class="caption-title">
<span style="margin-right: 30px;">{{ $t('log.title') }}</span>
</a-app>
<a-button
type="primary"
style="margin-right: 20px;"
@@ -106,13 +108,13 @@ function clearCaptions() {
<style scoped>
.caption-list {
background: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.caption-title {
display: inline-block;
font-size: 24px;
font-weight: bold;
margin-bottom: 10px;
@@ -139,13 +141,11 @@ function clearCaptions() {
.caption-text {
font-size: 16px;
color: #333;
margin-bottom: 4px;
}
.caption-translation {
font-size: 14px;
color: #666;
padding-left: 16px;
border-left: 3px solid #1890ff;
}

View File

@@ -19,6 +19,15 @@
</a-radio-group>
</div>
<div class="input-item">
<span class="input-label">{{ $t('general.theme') }}</span>
<a-radio-group v-model:value="uiTheme">
<a-radio-button value="system">{{ $t('general.system') }}</a-radio-button>
<a-radio-button value="light">{{ $t('general.light') }}</a-radio-button>
<a-radio-button value="dark">{{ $t('general.dark') }}</a-radio-button>
</a-radio-group>
</div>
<div class="input-item">
<span class="input-label">{{ $t('general.barWidth') }}</span>
<a-input
@@ -37,7 +46,7 @@ import { useGeneralSettingStore } from '@renderer/stores/generalSetting'
import { InfoCircleOutlined } from '@ant-design/icons-vue';
const generalSettingStore = useGeneralSettingStore()
const { uiLanguage, leftBarWidth } = storeToRefs(generalSettingStore)
const { uiLanguage, uiTheme, leftBarWidth } = storeToRefs(generalSettingStore)
</script>
<style scoped>

View File

@@ -0,0 +1,10 @@
import { theme } from 'ant-design-vue';
export const antDesignTheme = {
light: {
token: {}
},
dark: {
algorithm: theme.darkAlgorithm,
}
}

View File

@@ -16,3 +16,4 @@ export const i18n = createI18n({
export * from './config/engine'
export * from './config/audio'
export * from './config/theme'

View File

@@ -26,7 +26,11 @@ export default {
"title": "General Settings",
"uiLanguage": "Language",
"barWidth": "Width",
"note": "General Settings take effect immediately. Please note that changes to the Caption Engine Settings and Caption Style Settings will only take effect after clicking Apply."
"note": "General Settings take effect immediately. Please note that changes to the Caption Engine Settings and Caption Style Settings will only take effect after clicking Apply.",
"theme": "theme",
"light": "light",
"dark": "dark",
"system": "system"
},
engine: {
"title": "Caption Engine Settings",

View File

@@ -26,7 +26,11 @@ export default {
"title": "一般設定",
"uiLanguage": "言語設定",
"barWidth": "左側の幅",
"note": "一般設定はすぐに有効になります。字幕エンジンの設定と字幕スタイルの設定を変更した場合は、適用ボタンをクリックしてから有効になりますのでご注意ください。"
"note": "一般設定はすぐに有効になります。字幕エンジンの設定と字幕スタイルの設定を変更した場合は、適用ボタンをクリックしてから有効になりますのでご注意ください。",
"theme": "テーマ",
"light": "明るい",
"dark": "暗い",
"system": "システム"
},
engine: {
"title": "字幕エンジン設定",

View File

@@ -28,7 +28,11 @@ export default {
"title": "通用设置",
"uiLanguage": "界面语言",
"barWidth": "左侧宽度",
"note": "通用设置修改后立即生效。注意字幕引擎设置和字幕样式的设置修改后需要点击应用后才会生效。"
"note": "通用设置修改后立即生效。注意字幕引擎设置和字幕样式的设置修改后需要点击应用后才会生效。",
"theme": "主题",
"light": "浅色",
"dark": "深色",
"system": "系统"
},
engine: {
"title": "字幕引擎设置",

View File

@@ -1,4 +1,4 @@
import './assets/reset.css'
import './assets/main.css'
import { createApp } from 'vue'
import { createPinia } from 'pinia'

View File

@@ -1,15 +1,18 @@
import { ref, watch } from 'vue'
import { defineStore } from 'pinia'
import { i18n } from '../i18n'
import type { UILanguage } from '../types'
import type { UILanguage, UITheme } from '../types'
import { engines, audioTypes } from '../i18n'
import { engines, audioTypes, antDesignTheme } from '../i18n'
import { useEngineControlStore } from './engineControl'
export const useGeneralSettingStore = defineStore('generalSetting', () => {
const uiLanguage = ref<UILanguage>('zh')
const uiTheme = ref<UITheme>('system')
const leftBarWidth = ref<number>(8)
const antdTheme = ref<Object>(antDesignTheme['light'])
watch(uiLanguage, (newValue) => {
i18n.global.locale.value = newValue
useEngineControlStore().captionEngine = engines[newValue]
@@ -17,16 +20,47 @@ export const useGeneralSettingStore = defineStore('generalSetting', () => {
window.electron.ipcRenderer.send('control.uiLanguage.change', newValue)
})
watch(uiTheme, (newValue) => {
window.electron.ipcRenderer.send('control.uiTheme.change', newValue)
if(newValue === 'system'){
window.electron.ipcRenderer.invoke('control.nativeTheme.get').then((theme) => {
if(theme === 'light') setLightTheme()
else if(theme === 'dark') setDarkTheme()
})
}
else if(newValue === 'light') setLightTheme()
else if(newValue === 'dark') setDarkTheme()
})
watch(leftBarWidth, (newValue) => {
window.electron.ipcRenderer.send('control.leftBarWidth.change', newValue)
})
window.electron.ipcRenderer.on('caption.uiLanguage.set', (_, args: UILanguage) => {
window.electron.ipcRenderer.on('control.uiLanguage.set', (_, args: UILanguage) => {
uiLanguage.value = args
})
window.electron.ipcRenderer.on('control.nativeTheme.change', (_, args) => {
if(args === 'light') setLightTheme()
else if(args === 'dark') setDarkTheme()
})
function setLightTheme(){
antdTheme.value = antDesignTheme.light
const root = document.documentElement
root.style.setProperty('--control-background', '#fff')
}
function setDarkTheme(){
antdTheme.value = antDesignTheme.dark
const root = document.documentElement
root.style.setProperty('--control-background', '#000')
}
return {
uiLanguage,
leftBarWidth
uiTheme,
leftBarWidth,
antdTheme
}
})

View File

@@ -1,5 +1,7 @@
export type UILanguage = "zh" | "en" | "ja"
export type UITheme = "light" | "dark" | "system"
export interface Controls {
engineEnabled: boolean,
sourceLang: string,
@@ -35,6 +37,7 @@ export interface CaptionItem {
export interface FullConfig {
uiLanguage: UILanguage,
uiTheme: UITheme,
leftBarWidth: number,
styles: Styles,
controls: Controls,

View File

@@ -1,19 +1,21 @@
<template>
<a-row>
<a-col :span="leftBarWidth">
<div class="caption-control">
<GeneralSetting />
<EngineControl />
<CaptionStyle />
</div>
</a-col>
<a-col :span="24 - leftBarWidth">
<div class="caption-data">
<EngineStatus />
<CaptionLog />
</div>
</a-col>
</a-row>
<a-config-provider :theme="antdTheme">
<a-row class="control-container">
<a-col :span="leftBarWidth">
<div class="caption-control">
<GeneralSetting />
<EngineControl />
<CaptionStyle />
</div>
</a-col>
<a-col :span="24 - leftBarWidth">
<div class="caption-data">
<EngineStatus />
<CaptionLog />
</div>
</a-col>
</a-row>
</a-config-provider>
</template>
<script setup lang="ts">
@@ -26,22 +28,30 @@ import { storeToRefs } from 'pinia'
import { useGeneralSettingStore } from '@renderer/stores/generalSetting'
const generalSettingStore = useGeneralSettingStore()
const { leftBarWidth } = storeToRefs(generalSettingStore)
const { leftBarWidth, antdTheme } = storeToRefs(generalSettingStore)
</script>
<style scoped>
.control-container {
background-color: var(--control-background);
}
.caption-control {
height: 100vh;
border-right: 1px solid #7774;
padding: 20px;
overflow-y: auto;
scrollbar-width: thin;
}
.caption-data {
height: 100vh;
padding: 20px;
overflow-y: auto;
scrollbar-width: thin;
}
.caption-control::-webkit-scrollbar,
.caption-data::-webkit-scrollbar {
display: none;
}
</style>