mirror of
https://github.com/XiaoDaiGua-Ray/ray-template.git
synced 2025-04-04 22:28:40 +08:00
version: v5.0.3
This commit is contained in:
parent
7783872ef6
commit
8f3969268a
@ -1,5 +1,13 @@
|
||||
# CHANGE LOG
|
||||
|
||||
## 5.0.3
|
||||
|
||||
个性化配置能力再次提升。
|
||||
|
||||
## Feats
|
||||
|
||||
- `SettingDrawer` 组件重构
|
||||
|
||||
## 5.0.2
|
||||
|
||||
## Feats
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "ray-template",
|
||||
"private": false,
|
||||
"version": "5.0.2",
|
||||
"version": "5.0.3",
|
||||
"type": "module",
|
||||
"engines": {
|
||||
"node": "^18.0.0 || >=20.0.0",
|
||||
|
@ -26,7 +26,7 @@ export default defineComponent({
|
||||
const { getWatermarkConfig, getWatermarkSwitch } = this
|
||||
|
||||
return getWatermarkSwitch ? (
|
||||
<NWatermark cross fullscreen {...getWatermarkConfig} />
|
||||
<NWatermark {...getWatermarkConfig} fullscreen />
|
||||
) : null
|
||||
},
|
||||
})
|
||||
|
@ -11,7 +11,6 @@ export const APP_THEME: AppTheme = {
|
||||
'#3f9eff',
|
||||
'#ff42bc',
|
||||
'#ee4f12',
|
||||
'#a6e4f7',
|
||||
'#dbcb02',
|
||||
'#18A058',
|
||||
],
|
||||
|
@ -79,7 +79,8 @@ export default defineComponent({
|
||||
collapseMode={getMenuConfig.value.collapsedMode}
|
||||
collapsedWidth={getMenuConfig.value.collapsedWidth}
|
||||
onUpdateCollapsed={collapsedMenu.bind(this)}
|
||||
nativeScrollbar={false}
|
||||
width={getMenuConfig.value.menuWidth}
|
||||
nativeScrollbar={getMenuConfig.value.nativeScrollbar}
|
||||
ref={LAYOUT_SIDER_REF}
|
||||
collapsed={getCollapsed.value}
|
||||
onExpand={() => {
|
||||
@ -88,6 +89,7 @@ export default defineComponent({
|
||||
onCollapse={() => {
|
||||
updateMenuState('collapsed', true)
|
||||
}}
|
||||
inverted={getMenuConfig.value.inverted}
|
||||
>
|
||||
{getMenuConfig.value.menuSiderBarLogo ? (
|
||||
<SiderBarLogo collapsed={getCollapsed.value} />
|
||||
@ -107,6 +109,7 @@ export default defineComponent({
|
||||
}}
|
||||
accordion={getMenuConfig.value.accordion}
|
||||
iconSize={getMenuConfig.value.iconSize}
|
||||
inverted={getMenuConfig.value.inverted}
|
||||
/>
|
||||
</NLayoutSider>
|
||||
)
|
||||
|
@ -1,11 +1,30 @@
|
||||
import type { SettingState } from '@/store/modules/setting/types'
|
||||
import type { InjectionKey, Reactive } from 'vue'
|
||||
import type { DebouncedFunc } from 'lodash-es'
|
||||
|
||||
export const defaultSettingConfig: Partial<SettingState> = {
|
||||
type OmitKeys =
|
||||
| 'contentTransition'
|
||||
| 'watermarkSwitch'
|
||||
| 'keepAliveConfig'
|
||||
| 'menuConfig'
|
||||
| 'menuTagSwitch'
|
||||
| 'breadcrumbSwitch'
|
||||
| 'copyrightSwitch'
|
||||
| 'drawerPlacement'
|
||||
| 'colorWeakness'
|
||||
| 'watermarkConfig'
|
||||
| 'dynamicDocumentTitle'
|
||||
|
||||
interface Config extends Pick<SettingState, OmitKeys> {}
|
||||
|
||||
// SettingDrawer 默认配置系统配置项
|
||||
const defaultSettingConfig: Readonly<Partial<Config>> = {
|
||||
contentTransition: 'scale',
|
||||
watermarkSwitch: false,
|
||||
keepAliveConfig: {
|
||||
maxKeepAliveLength: 10,
|
||||
setupKeepAlive: true,
|
||||
keepAliveExclude: [],
|
||||
},
|
||||
menuConfig: {
|
||||
collapsedWidth: 64,
|
||||
@ -15,9 +34,55 @@ export const defaultSettingConfig: Partial<SettingState> = {
|
||||
accordion: false,
|
||||
menuSiderBarLogo: true,
|
||||
iconSize: 16,
|
||||
menuWidth: 272,
|
||||
inverted: false,
|
||||
nativeScrollbar: false,
|
||||
},
|
||||
menuTagSwitch: true,
|
||||
breadcrumbSwitch: true,
|
||||
copyrightSwitch: true,
|
||||
drawerPlacement: 'right',
|
||||
colorWeakness: false,
|
||||
watermarkConfig: {
|
||||
content: 'Trying be better~',
|
||||
fontSize: 16,
|
||||
lineHeight: 16,
|
||||
width: 384,
|
||||
height: 384,
|
||||
xOffset: 12,
|
||||
yOffset: 60,
|
||||
rotate: -15,
|
||||
xGap: 0,
|
||||
yGap: 0,
|
||||
cross: true,
|
||||
},
|
||||
dynamicDocumentTitle: true,
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @description
|
||||
* 获取默认配置。
|
||||
*/
|
||||
export const getDefaultSettingConfig = (): Partial<Config> => {
|
||||
return defaultSettingConfig
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param config 配置项
|
||||
*
|
||||
* @description
|
||||
* 更新默认配置。
|
||||
*/
|
||||
export const updateDefaultSettingConfig = (config: Partial<SettingState>) => {
|
||||
Object.assign(defaultSettingConfig, config)
|
||||
}
|
||||
|
||||
interface SettingDrawerInjectKey extends SettingState {
|
||||
throttleSetupAppMenu: DebouncedFunc<() => Promise<void>>
|
||||
}
|
||||
|
||||
export const SETTING_DRAWER_INJECT_KEY: Reactive<
|
||||
InjectionKey<Partial<SettingDrawerInjectKey>>
|
||||
> = Symbol('segmentDrawer')
|
||||
|
@ -1,8 +1,3 @@
|
||||
.setting-drawer__space {
|
||||
width: 100%;
|
||||
|
||||
& .n-descriptions-table-content {
|
||||
display: flex !important;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.n-form.setting-drawer__overrides-form .n-form-item .n-form-item-blank {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
@ -3,50 +3,30 @@ import './index.scss'
|
||||
import {
|
||||
NDrawer,
|
||||
NDrawerContent,
|
||||
NDivider,
|
||||
NFlex,
|
||||
NSwitch,
|
||||
NColorPicker,
|
||||
NDescriptions,
|
||||
NDescriptionsItem,
|
||||
NSelect,
|
||||
NInputNumber,
|
||||
NFormItem,
|
||||
NForm,
|
||||
NButton,
|
||||
NText,
|
||||
NTooltip,
|
||||
NTabs,
|
||||
NTabPane,
|
||||
} from 'naive-ui'
|
||||
import ThemeSegment from './components/ThemeSegment'
|
||||
import { RIcon } from '@/components'
|
||||
import SegmentViewsAppearance from './segment-views/Appearance'
|
||||
import SegmentViewsCommon from './segment-views/Common'
|
||||
import SegmentViewsWatermark from './segment-views/Watermark'
|
||||
import SegmentViewsCustomMenu from './segment-views/CustomMenu'
|
||||
|
||||
import { APP_THEME, CONTENT_TRANSITION_OPTIONS } from '@/app-config'
|
||||
import { useSettingGetters, useSettingActions, useMenuActions } from '@/store'
|
||||
import { defaultSettingConfig } from './constant'
|
||||
import { getDefaultSettingConfig, SETTING_DRAWER_INJECT_KEY } from './constant'
|
||||
import { forIn, throttle } from 'lodash-es'
|
||||
import { drawerProps } from 'naive-ui'
|
||||
import { useModal } from '@/components'
|
||||
|
||||
import type { PropType } from 'vue'
|
||||
import type { Placement } from '@/types'
|
||||
import type { SettingState } from '@/store/modules/setting/types'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SettingDrawer',
|
||||
props: {
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
placement: {
|
||||
type: String as PropType<Placement>,
|
||||
default: 'right',
|
||||
},
|
||||
width: {
|
||||
type: Number,
|
||||
default: 280,
|
||||
},
|
||||
},
|
||||
emits: ['update:show'],
|
||||
setup(props, { emit }) {
|
||||
props: drawerProps,
|
||||
setup() {
|
||||
const { create: createModal } = useModal()
|
||||
const { changePrimaryColor, updateSettingState } = useSettingActions()
|
||||
const {
|
||||
getAppTheme,
|
||||
@ -59,296 +39,94 @@ export default defineComponent({
|
||||
getKeepAliveConfig,
|
||||
getMenuConfig,
|
||||
getDrawerPlacement,
|
||||
getColorWeakness,
|
||||
getWatermarkConfig,
|
||||
getDynamicDocumentTitle,
|
||||
} = useSettingGetters()
|
||||
const { setupAppMenu } = useMenuActions()
|
||||
|
||||
const modelShow = computed({
|
||||
get: () => props.show,
|
||||
set: (bool) => {
|
||||
emit('update:show', bool)
|
||||
},
|
||||
})
|
||||
// 为了方便管理多个 computed,因为 computed 不能被逆向修改
|
||||
const modelReactive = computed({
|
||||
get: () => {
|
||||
return {
|
||||
getMenuTagSwitch: getMenuTagSwitch.value,
|
||||
getBreadcrumbSwitch: getBreadcrumbSwitch.value,
|
||||
getCopyrightSwitch: getCopyrightSwitch.value,
|
||||
getContentTransition: getContentTransition.value,
|
||||
getWatermarkSwitch: getWatermarkSwitch.value,
|
||||
getKeepAliveConfig: getKeepAliveConfig.value,
|
||||
getMenuConfig: getMenuConfig.value,
|
||||
getDrawerPlacement: getDrawerPlacement.value,
|
||||
}
|
||||
},
|
||||
set: (value) => {},
|
||||
})
|
||||
|
||||
const throttleSetupAppMenu = throttle(setupAppMenu, 300)
|
||||
const modelReactive = reactive({
|
||||
menuTagSwitch: getMenuTagSwitch.value,
|
||||
breadcrumbSwitch: getBreadcrumbSwitch.value,
|
||||
copyrightSwitch: getCopyrightSwitch.value,
|
||||
contentTransition: getContentTransition.value,
|
||||
watermarkSwitch: getWatermarkSwitch.value,
|
||||
keepAliveConfig: getKeepAliveConfig.value,
|
||||
menuConfig: getMenuConfig.value,
|
||||
drawerPlacement: getDrawerPlacement.value,
|
||||
colorWeakness: getColorWeakness.value,
|
||||
primaryColorOverride: getPrimaryColorOverride.value,
|
||||
watermarkConfig: getWatermarkConfig.value,
|
||||
dynamicDocumentTitle: getDynamicDocumentTitle.value,
|
||||
throttleSetupAppMenu,
|
||||
})
|
||||
|
||||
const defaultSettingBtnClick = () => {
|
||||
forIn(defaultSettingConfig, (value, key) => {
|
||||
updateSettingState(key as keyof SettingState, value)
|
||||
})
|
||||
createModal({
|
||||
preset: 'dialog',
|
||||
title: '恢复默认配置',
|
||||
type: 'warning',
|
||||
content: '点击【确认初始化】按钮会恢复默认系统配置,是否继续?',
|
||||
positiveText: '确认初始化',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: () => {
|
||||
forIn(getDefaultSettingConfig(), (value, key) => {
|
||||
modelReactive[key] = value
|
||||
|
||||
throttleSetupAppMenu()
|
||||
updateSettingState(key as keyof SettingState, value)
|
||||
})
|
||||
|
||||
throttleSetupAppMenu()
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
provide(SETTING_DRAWER_INJECT_KEY, modelReactive)
|
||||
|
||||
return {
|
||||
modelShow,
|
||||
changePrimaryColor,
|
||||
getAppTheme,
|
||||
getPrimaryColorOverride,
|
||||
updateSettingState,
|
||||
modelReactive,
|
||||
defaultSettingBtnClick,
|
||||
throttleSetupAppMenu,
|
||||
}
|
||||
},
|
||||
render() {
|
||||
const {
|
||||
$t,
|
||||
changePrimaryColor,
|
||||
updateSettingState,
|
||||
defaultSettingBtnClick,
|
||||
throttleSetupAppMenu,
|
||||
} = this
|
||||
const { defaultSettingBtnClick, $props } = this
|
||||
const { trapFocus, autoFocus, nativeScrollbar, ...restProps } = $props
|
||||
|
||||
return (
|
||||
<NDrawer
|
||||
v-model:show={this.modelShow}
|
||||
placement={this.placement}
|
||||
width={this.width}
|
||||
trapFocus={false}
|
||||
autoFocus={false}
|
||||
>
|
||||
<NDrawerContent title="系统配置">
|
||||
<NFlex class="setting-drawer__space" vertical>
|
||||
<NDivider titlePlacement="center">
|
||||
{$t('headerSettingOptions.ThemeOptions.Title')}
|
||||
</NDivider>
|
||||
<ThemeSegment />
|
||||
<NDivider titlePlacement="center">
|
||||
{$t('headerSettingOptions.ThemeOptions.PrimaryColorConfig')}
|
||||
</NDivider>
|
||||
<NColorPicker
|
||||
swatches={APP_THEME.appThemeColors}
|
||||
v-model:value={this.getPrimaryColorOverride.common!.primaryColor}
|
||||
onUpdateValue={changePrimaryColor.bind(this)}
|
||||
/>
|
||||
<NDivider titlePlacement="center">
|
||||
{$t('headerSettingOptions.ContentTransition')}
|
||||
</NDivider>
|
||||
<NSelect
|
||||
v-model:value={this.modelReactive.getContentTransition}
|
||||
options={CONTENT_TRANSITION_OPTIONS}
|
||||
onUpdateValue={(value) => {
|
||||
updateSettingState('contentTransition', value)
|
||||
}}
|
||||
/>
|
||||
<NDivider titlePlacement="center">抽屉位置</NDivider>
|
||||
<NSelect
|
||||
v-model:value={this.modelReactive.getDrawerPlacement}
|
||||
options={[
|
||||
{
|
||||
label: '右边',
|
||||
value: 'right',
|
||||
},
|
||||
{
|
||||
label: '左边',
|
||||
value: 'left',
|
||||
},
|
||||
]}
|
||||
onUpdateValue={(value) => {
|
||||
updateSettingState('drawerPlacement', value)
|
||||
}}
|
||||
/>
|
||||
<NDivider titlePlacement="center">系统设置</NDivider>
|
||||
<NDescriptions labelPlacement="left" column={1}>
|
||||
<NDescriptionsItem label="菜单页头">
|
||||
<NSwitch
|
||||
v-model:value={
|
||||
this.modelReactive.getMenuConfig.menuSiderBarLogo
|
||||
}
|
||||
onUpdateValue={(bool: boolean) =>
|
||||
updateSettingState('menuConfig', {
|
||||
menuSiderBarLogo: bool,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NDescriptionsItem>
|
||||
<NDescriptionsItem label="菜单手风琴">
|
||||
<NSwitch
|
||||
v-model:value={this.modelReactive.getMenuConfig.accordion}
|
||||
onUpdateValue={(bool: boolean) =>
|
||||
updateSettingState('menuConfig', {
|
||||
accordion: bool,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NDescriptionsItem>
|
||||
<NDescriptionsItem label="页面缓存">
|
||||
<NSwitch
|
||||
v-model:value={
|
||||
this.modelReactive.getKeepAliveConfig.setupKeepAlive
|
||||
}
|
||||
onUpdateValue={(bool: boolean) =>
|
||||
updateSettingState('keepAliveConfig', {
|
||||
setupKeepAlive: bool,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NDescriptionsItem>
|
||||
<NDescriptionsItem label="多标签">
|
||||
<NSwitch
|
||||
v-model:value={this.modelReactive.getMenuTagSwitch}
|
||||
onUpdateValue={(bool: boolean) =>
|
||||
updateSettingState('menuTagSwitch', bool)
|
||||
}
|
||||
/>
|
||||
</NDescriptionsItem>
|
||||
<NDescriptionsItem label="面包屑">
|
||||
<NSwitch
|
||||
v-model:value={this.modelReactive.getBreadcrumbSwitch}
|
||||
onUpdateValue={(bool: boolean) =>
|
||||
updateSettingState('breadcrumbSwitch', bool)
|
||||
}
|
||||
/>
|
||||
</NDescriptionsItem>
|
||||
<NDescriptionsItem label="水印">
|
||||
<NSwitch
|
||||
v-model:value={this.modelReactive.getWatermarkSwitch}
|
||||
onUpdateValue={(bool: boolean) =>
|
||||
updateSettingState('watermarkSwitch', bool)
|
||||
}
|
||||
/>
|
||||
</NDescriptionsItem>
|
||||
<NDescriptionsItem label="页底信息">
|
||||
<NSwitch
|
||||
v-model:value={this.modelReactive.getCopyrightSwitch}
|
||||
onUpdateValue={(bool: boolean) =>
|
||||
updateSettingState('copyrightSwitch', bool)
|
||||
}
|
||||
/>
|
||||
</NDescriptionsItem>
|
||||
</NDescriptions>
|
||||
<NDivider titlePlacement="center">
|
||||
<NFlex wrap={false} align="center" size={[4, 0]}>
|
||||
<NTooltip placement="top" showArrow={false}>
|
||||
<NDrawer {...restProps} trapFocus={false} autoFocus={false} width={320}>
|
||||
<NDrawerContent title="个性化配置" closable>
|
||||
{{
|
||||
default: () => (
|
||||
<NTabs type="bar" animated defaultValue="appearance">
|
||||
<NTabPane name="appearance" tab="外观">
|
||||
<SegmentViewsAppearance />
|
||||
</NTabPane>
|
||||
<NTabPane name="menu" tab="菜单">
|
||||
<SegmentViewsCustomMenu />
|
||||
</NTabPane>
|
||||
<NTabPane name="watermark" tab="水印">
|
||||
<SegmentViewsWatermark />
|
||||
</NTabPane>
|
||||
<NTabPane name="common" tab="通用">
|
||||
<SegmentViewsCommon />
|
||||
</NTabPane>
|
||||
</NTabs>
|
||||
),
|
||||
footer: () => (
|
||||
<NFlex justify="flex-start">
|
||||
<NButton type="warning" onClick={defaultSettingBtnClick}>
|
||||
{{
|
||||
trigger: () => <RIcon name="question" size="16" />,
|
||||
default: () => '菜单渲染是一个复杂、耗时的操作,请手动更新',
|
||||
}}
|
||||
</NTooltip>
|
||||
<NText>菜单样式</NText>
|
||||
</NFlex>
|
||||
</NDivider>
|
||||
<NForm showFeedback={true} showRequireMark={false}>
|
||||
<NFormItem label="每级菜单缩进">
|
||||
<NInputNumber
|
||||
v-model:value={
|
||||
this.modelReactive.getMenuConfig.collapsedIndent
|
||||
}
|
||||
min={0}
|
||||
precision={0}
|
||||
onUpdateValue={(value) => {
|
||||
if (value !== null) {
|
||||
updateSettingState('menuConfig', {
|
||||
collapsedIndent: value,
|
||||
})
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="菜单图标尺寸">
|
||||
<NInputNumber
|
||||
v-model:value={this.modelReactive.getMenuConfig.iconSize}
|
||||
min={0}
|
||||
precision={0}
|
||||
onUpdateValue={(value) => {
|
||||
if (value !== null) {
|
||||
updateSettingState('menuConfig', {
|
||||
iconSize: value,
|
||||
})
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="折叠菜单图标尺寸">
|
||||
<NInputNumber
|
||||
v-model:value={
|
||||
this.modelReactive.getMenuConfig.collapsedIconSize
|
||||
}
|
||||
min={0}
|
||||
precision={0}
|
||||
onUpdateValue={(value) => {
|
||||
if (value !== null) {
|
||||
updateSettingState('menuConfig', {
|
||||
collapsedIconSize: value,
|
||||
})
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="折叠菜单宽度">
|
||||
<NInputNumber
|
||||
v-model:value={
|
||||
this.modelReactive.getMenuConfig.collapsedWidth
|
||||
}
|
||||
min={0}
|
||||
precision={0}
|
||||
onUpdateValue={(value) => {
|
||||
if (value !== null) {
|
||||
updateSettingState('menuConfig', {
|
||||
collapsedWidth: value,
|
||||
})
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem showFeedback={false} showLabel={false}>
|
||||
<NButton
|
||||
onClick={throttleSetupAppMenu}
|
||||
block
|
||||
type="info"
|
||||
secondary
|
||||
>
|
||||
{{
|
||||
icon: () => <RIcon name="question" size="16" />,
|
||||
default: () => '点击刷新',
|
||||
icon: () => <RIcon name="reload" />,
|
||||
default: () => '初始化配置',
|
||||
}}
|
||||
</NButton>
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
<NDivider titlePlacement="center">
|
||||
<NFlex wrap={false} align="center" size={[4, 0]}>
|
||||
<NTooltip placement="top" showArrow={false}>
|
||||
{{
|
||||
trigger: () => <RIcon name="question" size="16" />,
|
||||
default: () => '当设置为【0】时,缓存将会失效',
|
||||
}}
|
||||
</NTooltip>
|
||||
<NText>最大缓存数</NText>
|
||||
</NFlex>
|
||||
</NDivider>
|
||||
<NInputNumber
|
||||
v-model:value={
|
||||
this.modelReactive.getKeepAliveConfig.maxKeepAliveLength
|
||||
}
|
||||
showButton={true}
|
||||
min={0}
|
||||
max={100}
|
||||
precision={0}
|
||||
disabled={!this.modelReactive.getKeepAliveConfig.setupKeepAlive}
|
||||
/>
|
||||
<NDivider titlePlacement="center">操作</NDivider>
|
||||
<NFlex>
|
||||
<NButton type="primary" block onClick={defaultSettingBtnClick}>
|
||||
清除设置
|
||||
</NButton>
|
||||
</NFlex>
|
||||
</NFlex>
|
||||
),
|
||||
}}
|
||||
</NDrawerContent>
|
||||
</NDrawer>
|
||||
)
|
||||
|
@ -0,0 +1,117 @@
|
||||
import {
|
||||
NFlex,
|
||||
NColorPicker,
|
||||
NFormItem,
|
||||
NDivider,
|
||||
NSelect,
|
||||
NSwitch,
|
||||
NForm,
|
||||
} from 'naive-ui'
|
||||
import ThemeSegment from '../components/ThemeSegment'
|
||||
|
||||
import { SETTING_DRAWER_INJECT_KEY } from '../constant'
|
||||
import { APP_THEME, CONTENT_TRANSITION_OPTIONS } from '@/app-config'
|
||||
import { useSettingActions } from '@/store'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SegmentViewsAppearance',
|
||||
setup() {
|
||||
const model = inject(SETTING_DRAWER_INJECT_KEY, {})
|
||||
const { changePrimaryColor, updateSettingState, toggleColorWeakness } =
|
||||
useSettingActions()
|
||||
|
||||
return {
|
||||
toggleColorWeakness,
|
||||
model,
|
||||
changePrimaryColor,
|
||||
updateSettingState,
|
||||
}
|
||||
},
|
||||
render() {
|
||||
const {
|
||||
toggleColorWeakness,
|
||||
model,
|
||||
changePrimaryColor,
|
||||
updateSettingState,
|
||||
} = this
|
||||
|
||||
return (
|
||||
<NFlex vertical style="width: 100%;" size={[0, 0]}>
|
||||
<NDivider>系统主题</NDivider>
|
||||
<ThemeSegment />
|
||||
<NDivider>内置主题</NDivider>
|
||||
<NColorPicker
|
||||
showPreview
|
||||
swatches={APP_THEME.appThemeColors}
|
||||
v-model:value={model.primaryColorOverride!.common!.primaryColor}
|
||||
onUpdateValue={changePrimaryColor.bind(this)}
|
||||
/>
|
||||
<NDivider>切换动画</NDivider>
|
||||
<NSelect
|
||||
v-model:value={model.contentTransition}
|
||||
options={CONTENT_TRANSITION_OPTIONS}
|
||||
onUpdateValue={(value) => {
|
||||
updateSettingState('contentTransition', value)
|
||||
}}
|
||||
/>
|
||||
<NDivider>配置入口出现位置</NDivider>
|
||||
<NSelect
|
||||
v-model:value={model.drawerPlacement}
|
||||
options={[
|
||||
{
|
||||
label: '右边',
|
||||
value: 'right',
|
||||
},
|
||||
{
|
||||
label: '左边',
|
||||
value: 'left',
|
||||
},
|
||||
]}
|
||||
onUpdateValue={(value) => {
|
||||
updateSettingState('drawerPlacement', value)
|
||||
}}
|
||||
/>
|
||||
<NDivider>其他设置</NDivider>
|
||||
<NForm
|
||||
labelPlacement="left"
|
||||
class="setting-drawer__overrides-form"
|
||||
showFeedback={false}
|
||||
>
|
||||
<NFormItem label="面包屑">
|
||||
<NSwitch
|
||||
v-model:value={model.breadcrumbSwitch}
|
||||
onUpdateValue={(bool) =>
|
||||
updateSettingState('breadcrumbSwitch', bool)
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="标签页">
|
||||
<NSwitch
|
||||
v-model:value={model.menuTagSwitch}
|
||||
onUpdateValue={(bool) =>
|
||||
updateSettingState('menuTagSwitch', bool)
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="页底信息">
|
||||
<NSwitch
|
||||
v-model:value={model.copyrightSwitch}
|
||||
onUpdateValue={(bool) =>
|
||||
updateSettingState('copyrightSwitch', bool)
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="色弱模式">
|
||||
<NSwitch
|
||||
v-model:value={model.colorWeakness}
|
||||
onUpdateValue={(bool) => {
|
||||
updateSettingState('colorWeakness', bool)
|
||||
toggleColorWeakness(bool)
|
||||
}}
|
||||
/>
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
</NFlex>
|
||||
)
|
||||
},
|
||||
})
|
@ -0,0 +1,98 @@
|
||||
import {
|
||||
NFlex,
|
||||
NFormItem,
|
||||
NDivider,
|
||||
NSwitch,
|
||||
NForm,
|
||||
NInputNumber,
|
||||
NDynamicTags,
|
||||
} from 'naive-ui'
|
||||
import { RIcon } from '@/components'
|
||||
|
||||
import { SETTING_DRAWER_INJECT_KEY } from '../constant'
|
||||
import { useSettingActions } from '@/store'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SegmentViewsCommon',
|
||||
setup() {
|
||||
const model = inject(SETTING_DRAWER_INJECT_KEY, {})
|
||||
const { updateSettingState } = useSettingActions()
|
||||
|
||||
return {
|
||||
model,
|
||||
updateSettingState,
|
||||
}
|
||||
},
|
||||
render() {
|
||||
const { model, updateSettingState } = this
|
||||
|
||||
return (
|
||||
<NFlex vertical style="width: 100%;" size={[0, 0]}>
|
||||
<NDivider>基础设置</NDivider>
|
||||
<NForm
|
||||
labelPlacement="left"
|
||||
class="setting-drawer__overrides-form"
|
||||
showFeedback={false}
|
||||
>
|
||||
<NFormItem label="页面缓存">
|
||||
<NSwitch
|
||||
v-model:value={model.keepAliveConfig!.setupKeepAlive}
|
||||
onUpdateValue={(bool) =>
|
||||
updateSettingState('keepAliveConfig', {
|
||||
setupKeepAlive: bool,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="动态浏览器标题">
|
||||
<NSwitch
|
||||
v-model:value={model.dynamicDocumentTitle}
|
||||
onUpdateValue={(bool) =>
|
||||
updateSettingState('dynamicDocumentTitle', bool)
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
<NDivider>缓存设置</NDivider>
|
||||
<NForm
|
||||
labelPlacement="top"
|
||||
showFeedback={true}
|
||||
showRequireMark={false}
|
||||
model={model.keepAliveConfig}
|
||||
>
|
||||
<NFormItem
|
||||
label="最大缓存数"
|
||||
feedback={
|
||||
computed(() => {
|
||||
if (model.keepAliveConfig!.maxKeepAliveLength <= 0) {
|
||||
return '设置为【0】时,缓存将会失效'
|
||||
}
|
||||
|
||||
return ''
|
||||
}).value
|
||||
}
|
||||
>
|
||||
<NInputNumber
|
||||
disabled={!model.keepAliveConfig!.setupKeepAlive}
|
||||
v-model:value={model.keepAliveConfig!.maxKeepAliveLength}
|
||||
min={0}
|
||||
precision={0}
|
||||
showButton={false}
|
||||
onUpdateValue={(val) =>
|
||||
updateSettingState('keepAliveConfig', {
|
||||
maxKeepAliveLength: val!,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="排除缓存">
|
||||
<NDynamicTags
|
||||
type="success"
|
||||
v-model:value={model.keepAliveConfig!.keepAliveExclude}
|
||||
/>
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
</NFlex>
|
||||
)
|
||||
},
|
||||
})
|
@ -0,0 +1,167 @@
|
||||
import {
|
||||
NFlex,
|
||||
NFormItem,
|
||||
NDivider,
|
||||
NSwitch,
|
||||
NForm,
|
||||
NTooltip,
|
||||
NText,
|
||||
NInputNumber,
|
||||
NButton,
|
||||
} from 'naive-ui'
|
||||
import { RIcon } from '@/components'
|
||||
|
||||
import { SETTING_DRAWER_INJECT_KEY } from '../constant'
|
||||
import { useSettingActions } from '@/store'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SegmentViewsCustomMenu',
|
||||
setup() {
|
||||
const model = inject(SETTING_DRAWER_INJECT_KEY, {})
|
||||
const { updateSettingState } = useSettingActions()
|
||||
|
||||
return {
|
||||
model,
|
||||
updateSettingState,
|
||||
}
|
||||
},
|
||||
render() {
|
||||
const { model, updateSettingState } = this
|
||||
|
||||
return (
|
||||
<NFlex vertical style="width: 100%;" size={[0, 0]}>
|
||||
<NDivider titlePlacement="center">
|
||||
<NFlex wrap={false} align="center" size={[4, 0]}>
|
||||
<NTooltip placement="top" showArrow={false}>
|
||||
{{
|
||||
trigger: () => <RIcon name="question" size="16" />,
|
||||
default: () =>
|
||||
'菜单更新是一个复杂、耗时的操作,请手动点击【更新菜单】按钮更新设置',
|
||||
}}
|
||||
</NTooltip>
|
||||
<NText>菜单样式</NText>
|
||||
</NFlex>
|
||||
</NDivider>
|
||||
<NForm
|
||||
showFeedback={true}
|
||||
showRequireMark={false}
|
||||
class="setting-drawer__overrides-form"
|
||||
>
|
||||
<NFormItem label="每级菜单缩进">
|
||||
<NInputNumber
|
||||
v-model:value={model.menuConfig!.collapsedIndent}
|
||||
min={0}
|
||||
precision={0}
|
||||
onUpdateValue={(value) =>
|
||||
updateSettingState('menuConfig', {
|
||||
collapsedIndent: value!,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="菜单图标尺寸">
|
||||
<NInputNumber
|
||||
v-model:value={model.menuConfig!.iconSize}
|
||||
min={0}
|
||||
precision={0}
|
||||
onUpdateValue={(value) =>
|
||||
updateSettingState('menuConfig', {
|
||||
iconSize: value!,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="折叠菜单图标尺寸">
|
||||
<NInputNumber
|
||||
v-model:value={model.menuConfig!.collapsedIconSize}
|
||||
min={0}
|
||||
precision={0}
|
||||
onUpdateValue={(value) =>
|
||||
updateSettingState('menuConfig', {
|
||||
collapsedIconSize: value!,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="菜单宽度">
|
||||
<NInputNumber
|
||||
v-model:value={model.menuConfig!.menuWidth}
|
||||
min={0}
|
||||
precision={0}
|
||||
onUpdateValue={(value) =>
|
||||
updateSettingState('menuConfig', {
|
||||
menuWidth: value!,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="折叠菜单宽度">
|
||||
<NInputNumber
|
||||
v-model:value={model.menuConfig!.collapsedWidth}
|
||||
min={0}
|
||||
precision={0}
|
||||
onUpdateValue={(value) =>
|
||||
updateSettingState('menuConfig', {
|
||||
collapsedWidth: value!,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem showFeedback={false} showLabel={false}>
|
||||
<NButton onClick={model.throttleSetupAppMenu} block type="primary">
|
||||
更新菜单
|
||||
</NButton>
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
<NDivider>其他设置</NDivider>
|
||||
<NForm
|
||||
showFeedback={false}
|
||||
showRequireMark={false}
|
||||
class="setting-drawer__overrides-form"
|
||||
labelPlacement="left"
|
||||
>
|
||||
<NFormItem label="反转色菜单">
|
||||
<NSwitch
|
||||
v-model:value={model.menuConfig!.inverted}
|
||||
onUpdateValue={(bool) =>
|
||||
updateSettingState('menuConfig', {
|
||||
inverted: bool,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="菜单标题">
|
||||
<NSwitch
|
||||
v-model:value={model.menuConfig!.menuSiderBarLogo}
|
||||
onUpdateValue={(bool) =>
|
||||
updateSettingState('menuConfig', {
|
||||
menuSiderBarLogo: bool,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="手风琴菜单">
|
||||
<NSwitch
|
||||
v-model:value={model.menuConfig!.accordion}
|
||||
onUpdateValue={(bool) =>
|
||||
updateSettingState('menuConfig', {
|
||||
accordion: bool,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="原生滚动条">
|
||||
<NSwitch
|
||||
v-model:value={model.menuConfig!.nativeScrollbar}
|
||||
onUpdateValue={(bool) =>
|
||||
updateSettingState('menuConfig', {
|
||||
nativeScrollbar: bool,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
</NFlex>
|
||||
)
|
||||
},
|
||||
})
|
@ -0,0 +1,184 @@
|
||||
import {
|
||||
NFlex,
|
||||
NFormItem,
|
||||
NDivider,
|
||||
NSwitch,
|
||||
NForm,
|
||||
NInputNumber,
|
||||
NInput,
|
||||
} from 'naive-ui'
|
||||
|
||||
import { SETTING_DRAWER_INJECT_KEY } from '../constant'
|
||||
import { useSettingActions } from '@/store'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SegmentViewsWatermark',
|
||||
setup() {
|
||||
const model = inject(SETTING_DRAWER_INJECT_KEY, {})
|
||||
const { updateSettingState } = useSettingActions()
|
||||
|
||||
return {
|
||||
model,
|
||||
updateSettingState,
|
||||
}
|
||||
},
|
||||
render() {
|
||||
const { model, updateSettingState } = this
|
||||
|
||||
return (
|
||||
<NFlex vertical style="width: 100%;" size={[0, 0]}>
|
||||
<NDivider>基础设置</NDivider>
|
||||
<NForm
|
||||
showFeedback={false}
|
||||
showRequireMark={false}
|
||||
class="setting-drawer__overrides-form"
|
||||
labelPlacement="left"
|
||||
>
|
||||
<NFormItem label="全屏水印">
|
||||
<NSwitch
|
||||
v-model:value={model.watermarkSwitch}
|
||||
onUpdateValue={(bool) =>
|
||||
updateSettingState('watermarkSwitch', bool)
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="跨边界显示">
|
||||
<NSwitch
|
||||
v-model:value={model.watermarkConfig!.cross}
|
||||
onUpdateValue={(val) =>
|
||||
updateSettingState('watermarkConfig', {
|
||||
cross: val,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
<NDivider>个性化水印</NDivider>
|
||||
<NForm
|
||||
showFeedback={true}
|
||||
showRequireMark={false}
|
||||
class="setting-drawer__overrides-form"
|
||||
>
|
||||
<NFormItem label="水印内容">
|
||||
<NInput
|
||||
v-model:value={model.watermarkConfig!.content}
|
||||
onUpdateValue={(val) =>
|
||||
updateSettingState('watermarkConfig', {
|
||||
content: val,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="字体尺寸">
|
||||
<NInputNumber
|
||||
precision={0}
|
||||
showButton={false}
|
||||
v-model:value={model.watermarkConfig!.fontSize}
|
||||
onUpdateValue={(val) =>
|
||||
updateSettingState('watermarkConfig', {
|
||||
fontSize: val!,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="字体行高">
|
||||
<NInputNumber
|
||||
precision={0}
|
||||
showButton={false}
|
||||
v-model:value={model.watermarkConfig!.lineHeight}
|
||||
onUpdateValue={(val) =>
|
||||
updateSettingState('watermarkConfig', {
|
||||
lineHeight: val!,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="字体宽度">
|
||||
<NInputNumber
|
||||
precision={0}
|
||||
showButton={false}
|
||||
v-model:value={model.watermarkConfig!.width}
|
||||
onUpdateValue={(val) =>
|
||||
updateSettingState('watermarkConfig', {
|
||||
width: val!,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="字体高度">
|
||||
<NInputNumber
|
||||
precision={0}
|
||||
showButton={false}
|
||||
v-model:value={model.watermarkConfig!.height}
|
||||
onUpdateValue={(val) =>
|
||||
updateSettingState('watermarkConfig', {
|
||||
height: val!,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="x轴偏移">
|
||||
<NInputNumber
|
||||
precision={0}
|
||||
showButton={false}
|
||||
v-model:value={model.watermarkConfig!.xOffset}
|
||||
onUpdateValue={(val) =>
|
||||
updateSettingState('watermarkConfig', {
|
||||
xOffset: val!,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="x轴间隙">
|
||||
<NInputNumber
|
||||
precision={0}
|
||||
showButton={false}
|
||||
v-model:value={model.watermarkConfig!.xGap}
|
||||
onUpdateValue={(val) =>
|
||||
updateSettingState('watermarkConfig', {
|
||||
xGap: val!,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="y轴偏移">
|
||||
<NInputNumber
|
||||
precision={0}
|
||||
showButton={false}
|
||||
v-model:value={model.watermarkConfig!.yOffset}
|
||||
onUpdateValue={(val) =>
|
||||
updateSettingState('watermarkConfig', {
|
||||
yOffset: val!,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="y轴间隙">
|
||||
<NInputNumber
|
||||
precision={0}
|
||||
showButton={false}
|
||||
v-model:value={model.watermarkConfig!.yGap}
|
||||
onUpdateValue={(val) =>
|
||||
updateSettingState('watermarkConfig', {
|
||||
yGap: val!,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="旋转角度">
|
||||
<NInputNumber
|
||||
precision={0}
|
||||
showButton={false}
|
||||
v-model:value={model.watermarkConfig!.rotate}
|
||||
onUpdateValue={(val) =>
|
||||
updateSettingState('watermarkConfig', {
|
||||
rotate: val!,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
</NFlex>
|
||||
)
|
||||
},
|
||||
})
|
@ -105,6 +105,20 @@ export const useSettingGetters = () => {
|
||||
*/
|
||||
const getMenuConfig = computed(() => variable.menuConfig)
|
||||
|
||||
/**
|
||||
*
|
||||
* @description
|
||||
* 获取是否启用色弱模式。
|
||||
*/
|
||||
const getColorWeakness = computed(() => variable.colorWeakness)
|
||||
|
||||
/**
|
||||
*
|
||||
* @description
|
||||
* 是否启用动态浏览器标题。
|
||||
*/
|
||||
const getDynamicDocumentTitle = computed(() => variable.dynamicDocumentTitle)
|
||||
|
||||
return {
|
||||
getDrawerPlacement,
|
||||
getPrimaryColorOverride,
|
||||
@ -122,16 +136,23 @@ export const useSettingGetters = () => {
|
||||
getKeepAliveConfig,
|
||||
getMenuConfig,
|
||||
getAppThemeStr,
|
||||
getColorWeakness,
|
||||
getDynamicDocumentTitle,
|
||||
}
|
||||
}
|
||||
|
||||
export const useSettingActions = () => {
|
||||
const { updateLocale, changePrimaryColor, updateSettingState } =
|
||||
piniaSettingStore()
|
||||
const {
|
||||
updateLocale,
|
||||
changePrimaryColor,
|
||||
updateSettingState,
|
||||
toggleColorWeakness,
|
||||
} = piniaSettingStore()
|
||||
|
||||
return {
|
||||
updateLocale,
|
||||
changePrimaryColor,
|
||||
updateSettingState,
|
||||
toggleColorWeakness,
|
||||
}
|
||||
}
|
||||
|
@ -109,6 +109,12 @@ export const parseAndFindMatchingNodes = (
|
||||
* 会自动拼接 sideBarLogo.title。
|
||||
*/
|
||||
export const updateDocumentTitle = (option: AppMenuOption) => {
|
||||
const { dynamicDocumentTitle } = piniaSettingStore()
|
||||
|
||||
if (!dynamicDocumentTitle) {
|
||||
return
|
||||
}
|
||||
|
||||
const { breadcrumbLabel } = option
|
||||
|
||||
if (!breadcrumbLabel) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { getAppDefaultLanguage } from '@/locales/utils'
|
||||
import { colorToRgba, setStorage, updateObjectValue } from '@/utils'
|
||||
import { colorToRgba, setStorage, updateObjectValue, setStyle } from '@/utils'
|
||||
import { useI18n, useDayjs } from '@/hooks'
|
||||
import { APP_CATCH_KEY, APP_THEME } from '@/app-config'
|
||||
|
||||
@ -52,8 +52,11 @@ export const piniaSettingStore = defineStore(
|
||||
width: 384,
|
||||
height: 384,
|
||||
xOffset: 12,
|
||||
xGap: 0,
|
||||
yGap: 0,
|
||||
yOffset: 60,
|
||||
rotate: -15,
|
||||
cross: true,
|
||||
},
|
||||
// 根路由信息
|
||||
appRootRoute: {
|
||||
@ -82,7 +85,14 @@ export const piniaSettingStore = defineStore(
|
||||
accordion: false,
|
||||
menuSiderBarLogo: true,
|
||||
iconSize: 16,
|
||||
menuWidth: 272,
|
||||
inverted: false,
|
||||
nativeScrollbar: false,
|
||||
},
|
||||
// 色弱模式
|
||||
colorWeakness: false,
|
||||
// 动态标题
|
||||
dynamicDocumentTitle: true,
|
||||
})
|
||||
|
||||
// 修改当前语言
|
||||
@ -125,7 +135,6 @@ export const piniaSettingStore = defineStore(
|
||||
*
|
||||
* @description
|
||||
* 更新 settingState 的值,如果 key 不存在与 settingState 中,则不会更新。
|
||||
* 但是不论是否更新成功,都会执行回调函数。
|
||||
*
|
||||
* @example
|
||||
* updateSettingState('drawerPlacement', 'left')
|
||||
@ -143,39 +152,49 @@ export const piniaSettingStore = defineStore(
|
||||
updateObjectValue(settingState, key, value, cb)
|
||||
}
|
||||
|
||||
const toggleColorWeakness = (bool: boolean) => {
|
||||
const html = document.documentElement
|
||||
|
||||
updateSettingState('colorWeakness', bool)
|
||||
setStyle(html, {
|
||||
filter: bool ? 'invert(100%)' : '',
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 初始化合并自定义主题色
|
||||
* 该方法会在初始化时执行一次,之后会在切换主题色时执行
|
||||
* @description
|
||||
* 初始化合并自定义主题色。
|
||||
* 该方法会在初始化时执行一次,之后会在切换主题色时执行。
|
||||
*/
|
||||
watch(
|
||||
() => settingState.appTheme,
|
||||
(ndata) => {
|
||||
ndata
|
||||
? (settingState.primaryColorOverride = Object.assign(
|
||||
{},
|
||||
settingState.primaryColorOverride,
|
||||
APP_THEME.appNaiveUIThemeOverrides.dark,
|
||||
APP_THEME.appNaiveUIThemeOverridesCommon.dark,
|
||||
))
|
||||
: (settingState.primaryColorOverride = Object.assign(
|
||||
{},
|
||||
settingState.primaryColorOverride,
|
||||
APP_THEME.appNaiveUIThemeOverrides.light,
|
||||
APP_THEME.appNaiveUIThemeOverridesCommon.light,
|
||||
))
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
once: true,
|
||||
},
|
||||
)
|
||||
watchEffect(() => {
|
||||
settingState.appTheme
|
||||
? (settingState.primaryColorOverride = Object.assign(
|
||||
{},
|
||||
settingState.primaryColorOverride,
|
||||
APP_THEME.appNaiveUIThemeOverrides.dark,
|
||||
APP_THEME.appNaiveUIThemeOverridesCommon.dark,
|
||||
))
|
||||
: (settingState.primaryColorOverride = Object.assign(
|
||||
{},
|
||||
settingState.primaryColorOverride,
|
||||
APP_THEME.appNaiveUIThemeOverrides.light,
|
||||
APP_THEME.appNaiveUIThemeOverridesCommon.light,
|
||||
))
|
||||
|
||||
toggleColorWeakness(settingState.colorWeakness)
|
||||
|
||||
if (!settingState.dynamicDocumentTitle) {
|
||||
document.title = settingState.sideBarLogo?.title || 'Ray Template'
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
...toRefs(settingState),
|
||||
updateLocale,
|
||||
changePrimaryColor,
|
||||
updateSettingState,
|
||||
toggleColorWeakness,
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -14,7 +14,10 @@ export interface WatermarkConfig {
|
||||
height: number
|
||||
xOffset: number
|
||||
yOffset: number
|
||||
xGap: number
|
||||
yGap: number
|
||||
rotate: number
|
||||
cross: boolean
|
||||
}
|
||||
|
||||
export interface AppRootRoute {
|
||||
@ -70,4 +73,12 @@ export interface SettingState {
|
||||
* accordion 手风琴模式
|
||||
*/
|
||||
menuConfig: AppMenuConfig
|
||||
colorWeakness: boolean
|
||||
/**
|
||||
*
|
||||
* @description
|
||||
* 动态浏览器标题。
|
||||
* 如果设置为 true,会在更新菜单时,自动取用当前菜单的标题作为浏览器标题。
|
||||
*/
|
||||
dynamicDocumentTitle: boolean
|
||||
}
|
||||
|
@ -10,11 +10,14 @@ export interface AppMenuConfig {
|
||||
accordion: boolean
|
||||
menuSiderBarLogo: boolean
|
||||
iconSize: number
|
||||
menuWidth: number
|
||||
inverted: boolean
|
||||
nativeScrollbar: boolean
|
||||
}
|
||||
|
||||
export interface AppKeepAlive {
|
||||
setupKeepAlive: boolean
|
||||
keepAliveExclude?: string[]
|
||||
keepAliveExclude: string[]
|
||||
maxKeepAliveLength: number
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* 从目标类型中挑选出符合条件的属性名
|
||||
* @description
|
||||
* 从目标类型中挑选出符合条件的属性名。
|
||||
*
|
||||
* @example
|
||||
* ConditionalKeys<{ a: string, b: number }, string> // 'a'
|
||||
@ -15,7 +16,8 @@ export type ConditionalKeys<Base, Condition> = NonNullable<
|
||||
|
||||
/**
|
||||
*
|
||||
* 从目标类型中排除符合条件的属性
|
||||
* @description
|
||||
* 从目标类型中排除符合条件的属性。
|
||||
*
|
||||
* @example
|
||||
* ConditionalExclude<{ a: string, b: number }, string> // { b: number }
|
||||
@ -27,7 +29,8 @@ export type ConditionalExclude<Base, Condition> = Omit<
|
||||
|
||||
/**
|
||||
*
|
||||
* 从目标类型中挑选出符合条件的属性
|
||||
* @description
|
||||
* 从目标类型中挑选出符合条件的属性。
|
||||
*
|
||||
* @example
|
||||
* ConditionalPick<{ a: string, b: number }, string> // { a: string }
|
||||
@ -39,7 +42,8 @@ export type ConditionalPick<Base, Condition> = Pick<
|
||||
|
||||
/**
|
||||
*
|
||||
* 声明一个任意类型的对象
|
||||
* @description
|
||||
* 声明一个任意类型的对象。
|
||||
*
|
||||
* @example
|
||||
* const A: Recordable = { a: 1, b: [] }
|
||||
@ -48,7 +52,8 @@ export type Recordable<T = any> = Record<string, T>
|
||||
|
||||
/**
|
||||
*
|
||||
* 获取目标类型的所有属性类型
|
||||
* @description
|
||||
* 获取目标类型的所有属性类型。
|
||||
*
|
||||
* @example
|
||||
* ValueOf<{ a: string, b: number }> // string | number
|
||||
@ -57,7 +62,8 @@ export type ValueOf<T extends object> = T[keyof T]
|
||||
|
||||
/**
|
||||
*
|
||||
* 将目标所有属性变为可修改
|
||||
* @description
|
||||
* 将目标所有属性变为可修改。
|
||||
*
|
||||
* @example
|
||||
* Mutable<{ readonly a: string }> // { a: string }
|
||||
@ -68,7 +74,8 @@ export type Mutable<T> = {
|
||||
|
||||
/**
|
||||
*
|
||||
* 递归将目标所有属性变为可修改
|
||||
* @description
|
||||
* 递归将目标所有属性变为可修改。
|
||||
*
|
||||
* @example
|
||||
* DeepMutable<{ readonly a: { readonly b: { readonly c: string } } }> // { a: { b: { c: string } } }
|
||||
@ -83,7 +90,8 @@ export type DeepMutable<T> = {
|
||||
|
||||
/**
|
||||
*
|
||||
* 获取 Promise 返回值类型
|
||||
* @description
|
||||
* 获取 Promise 返回值类型。
|
||||
*
|
||||
* @example
|
||||
* ReturnPromiseType<Promise<string>> // string
|
||||
@ -91,3 +99,17 @@ export type DeepMutable<T> = {
|
||||
*/
|
||||
export type ReturnPromiseType<T extends Promise<any>> =
|
||||
T extends Promise<infer U> ? U : never
|
||||
|
||||
/**
|
||||
*
|
||||
* @description
|
||||
* 深度只读。
|
||||
*
|
||||
* @example
|
||||
* DeepReadonly<{ a: { b: string } }> // { readonly a: { readonly b: string } }
|
||||
*/
|
||||
export type DeepReadonly<T> = T extends object
|
||||
? {
|
||||
readonly [P in keyof T]: DeepReadonly<T[P]>
|
||||
}
|
||||
: T
|
||||
|
Loading…
x
Reference in New Issue
Block a user