mirror of
https://github.com/fantastic-admin/basic.git
synced 2026-10-07 17:28:24 +08:00
177 lines
5.1 KiB
TypeScript
Executable File
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
|