Files
basic/src/store/modules/settings.ts
T

177 lines
5.1 KiB
TypeScript
Executable File

import type { Settings } from '#/global'
import type { RouteMeta } from 'vue-router'
import settingsDefault from '@/settings'
import { merge } from '@/utils/object'
import { cloneDeep } from 'es-toolkit'
const useSettingsStore = defineStore(
// 唯一ID
'settings',
() => {
const settings = ref(settingsDefault)
const prefersColorScheme = window.matchMedia('(prefers-color-scheme: dark)')
watch(() => settings.value.app.colorScheme, (val) => {
if (val === '') {
prefersColorScheme.addEventListener('change', updateTheme)
}
else {
prefersColorScheme.removeEventListener('change', updateTheme)
}
}, {
immediate: true,
})
const currentColorScheme = ref<Exclude<Settings.app['colorScheme'], ''>>()
watch(() => settings.value.app.colorScheme, updateTheme, {
immediate: true,
})
function updateTheme() {
let colorScheme = settings.value.app.colorScheme
if (colorScheme === '') {
colorScheme = prefersColorScheme.matches ? 'dark' : 'light'
}
currentColorScheme.value = colorScheme
switch (colorScheme) {
case 'light':
document.documentElement.classList.remove('dark')
break
case 'dark':
document.documentElement.classList.add('dark')
break
}
}
watch(() => settings.value.app.radius, (val) => {
document.documentElement.style.removeProperty('--radius')
document.documentElement.style.setProperty('--radius', `${val}rem`)
}, {
immediate: true,
})
watch([
() => settings.value.app.enableMournMode,
() => settings.value.app.enableColorAmblyopiaMode,
], (val) => {
document.documentElement.style.removeProperty('filter')
if (val[0] && val[1]) {
document.documentElement.style.setProperty('filter', 'grayscale(100%) invert(80%)')
}
else if (val[0]) {
document.documentElement.style.setProperty('filter', 'grayscale(100%)')
}
else if (val[1]) {
document.documentElement.style.setProperty('filter', 'invert(80%)')
}
}, {
immediate: true,
})
watch(() => settings.value.menu.mode, (val) => {
document.body.setAttribute('data-menu-mode', val)
}, {
immediate: true,
})
// 操作系统
const os = ref<'mac' | 'windows' | 'linux' | 'other'>('other')
const agent = navigator.userAgent.toLowerCase()
switch (true) {
case agent.includes('mac os'):
os.value = 'mac'
break
case agent.includes('windows'):
os.value = 'windows'
break
case agent.includes('linux'):
os.value = 'linux'
break
}
// 页面是否刷新
const isReloading = ref(false)
// 切换当前页面是否刷新
function setIsReloading(value?: boolean) {
isReloading.value = value ?? !isReloading.value
}
// 页面标题
const title = ref<RouteMeta['title']>()
// 记录页面标题
function setTitle(_title: RouteMeta['title']) {
title.value = _title
}
// 显示模式
const mode = ref<'pc' | 'mobile'>('pc')
// 设置显示模式
function setMode(width: number) {
if (settings.value.layout.enableMobileAdaptation) {
// 先判断 UA 是否为移动端设备(手机&平板)
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
mode.value = 'mobile'
}
else {
// 如果是桌面设备,则根据页面宽度判断是否需要切换为移动端展示
mode.value = width < 1024 ? 'mobile' : 'pc'
}
}
else {
mode.value = 'pc'
}
}
// 切换侧边栏导航展开/收起
function toggleSidebarCollapse() {
settings.value.menu.subMenuCollapse = !settings.value.menu.subMenuCollapse
}
// 次导航是否收起(用于记录 pc 模式下最后的状态)
const subMenuCollapseLastStatus = ref(settingsDefault.menu.subMenuCollapse)
watch(() => settings.value.menu.subMenuCollapse, (val) => {
if (mode.value === 'pc') {
subMenuCollapseLastStatus.value = val
}
})
watch(mode, (val) => {
switch (val) {
case 'pc':
settings.value.menu.subMenuCollapse = subMenuCollapseLastStatus.value
break
case 'mobile':
settings.value.menu.subMenuCollapse = true
break
}
document.body.setAttribute('data-mode', val)
}, {
immediate: true,
})
// 设置主题颜色模式
function setColorScheme(color: Required<Settings.app>['colorScheme']) {
settings.value.app.colorScheme = color
}
// 更新应用配置
function updateSettings(data: Settings.all, fromBase = false) {
settings.value = merge(data, fromBase ? cloneDeep(settingsDefault) : settings.value)
}
return {
settings,
currentColorScheme,
os,
isReloading,
setIsReloading,
title,
setTitle,
mode,
setMode,
subMenuCollapseLastStatus,
toggleSidebarCollapse,
setColorScheme,
updateSettings,
}
},
)
export default useSettingsStore