| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- /*
- * @Author: liuJie
- * @Date: 2026-01-30 19:47:19
- * @LastEditors: liuJie
- * @LastEditTime: 2026-01-30 20:20:59
- * @Describe: 单独抽离换肤
- */
- import { ref, onMounted, onBeforeUnmount } from 'vue'
- import * as monaco from 'monaco-editor'
- type EditorTheme = 'vs-light' | 'vs-dark'
- type ThemeClass = 'light' | 'dark'
- interface UseLocalEditorThemeOptions {
- defaultTheme?: EditorTheme
- autoToggleTheme?: boolean
- }
- export function useLocalEditorTheme(
- options: UseLocalEditorThemeOptions = {}
- ) {
- const {
- defaultTheme = 'vs-light',
- autoToggleTheme = false
- } = options
- /** 当前 Monaco 主题(语法) */
- const monacoTheme = ref<EditorTheme>(defaultTheme)
- /** 当前 UI 主题(样式) */
- const themeClass = ref<ThemeClass>(
- defaultTheme === 'vs-dark' ? 'dark' : 'light'
- )
- /** 系统暗黑监听 */
- let mediaQuery: MediaQueryList | null = null
- const applyTheme = (theme: EditorTheme) => {
- monacoTheme.value = theme
- themeClass.value = theme === 'vs-dark' ? 'dark' : 'light'
- monaco.editor.setTheme(theme)
- }
- /** 手动切换 */
- const toggleTheme = () => {
- applyTheme(
- monacoTheme.value === 'vs-light' ? 'vs-dark' : 'vs-light'
- )
- }
- /** 系统主题变化 */
- const handleSystemThemeChange = (e: MediaQueryListEvent) => {
- applyTheme(e.matches ? 'vs-dark' : 'vs-light')
- }
- onMounted(() => {
- applyTheme(defaultTheme)
- if (autoToggleTheme) {
- mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
- applyTheme(mediaQuery.matches ? 'vs-dark' : 'vs-light')
- mediaQuery.addEventListener('change', handleSystemThemeChange)
- }
- })
- onBeforeUnmount(() => {
- if (mediaQuery) {
- mediaQuery.removeEventListener('change', handleSystemThemeChange)
- }
- })
- return {
- monacoTheme,
- themeClass,
- toggleTheme,
- setTheme: applyTheme
- }
- }
|