增加配置项保存的实现
This commit is contained in:
@@ -1,92 +1,93 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { ConfigItemType, type ConfigGroup } from '@/types/config'
|
||||
import { ConfigGroup, TextConfigItem, SelectConfigItem, SwitchConfigItem, ConfigItemType } from '@/types/config'
|
||||
import { ConfigManager, LocalStorageConfigStore } from '@/utils/ConfigStore'
|
||||
|
||||
// 定义配置组
|
||||
const configGroups = ref<ConfigGroup[]>([
|
||||
{
|
||||
title: '外观设置',
|
||||
enabled: true,
|
||||
items: [
|
||||
{
|
||||
type: ConfigItemType.TEXT,
|
||||
key: 'projectName',
|
||||
label: '项目名称',
|
||||
value: '',
|
||||
placeholder: '请输入默认项目名称',
|
||||
description: '设置新建项目时的默认项目名称'
|
||||
},
|
||||
{
|
||||
type: ConfigItemType.SELECT,
|
||||
key: 'theme',
|
||||
label: '主题',
|
||||
value: 'light',
|
||||
description: '切换应用的显示主题',
|
||||
options: [
|
||||
{ label: '浅色', value: 'light' },
|
||||
{ label: '深色', value: 'dark' }
|
||||
]
|
||||
const configManager = ConfigManager.getInstance(new LocalStorageConfigStore())
|
||||
|
||||
// 防抖函数
|
||||
const debounce = (fn: Function, delay: number) => {
|
||||
let timer: number | null = null
|
||||
return (...args: any[]) => {
|
||||
if (timer) clearTimeout(timer)
|
||||
timer = setTimeout(() => {
|
||||
fn(...args)
|
||||
timer = null
|
||||
}, delay)
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '系统设置',
|
||||
enabled: true,
|
||||
items: [
|
||||
{
|
||||
type: ConfigItemType.SELECT,
|
||||
key: 'language',
|
||||
label: '语言',
|
||||
value: 'zh-CN',
|
||||
description: '设置应用界面显示的语言',
|
||||
options: [
|
||||
{ label: '中文', value: 'zh-CN' },
|
||||
{ label: 'English', value: 'en-US' }
|
||||
]
|
||||
},
|
||||
{
|
||||
type: ConfigItemType.SWITCH,
|
||||
key: 'autoSave',
|
||||
label: '自动保存',
|
||||
value: true,
|
||||
description: '开启后将自动保存您的修改'
|
||||
},
|
||||
{
|
||||
type: ConfigItemType.SWITCH,
|
||||
key: 'notifications',
|
||||
label: '通知提醒',
|
||||
value: true,
|
||||
description: '是否显示系统通知提醒'
|
||||
}
|
||||
]
|
||||
}
|
||||
])
|
||||
}
|
||||
|
||||
// 处理文本配置项实时更新
|
||||
const handleTextConfigChange = debounce((item: TextConfigItem, group: ConfigGroup) => {
|
||||
configManager.updateConfig({
|
||||
[`${group.key}.${item.key}`]: item.value
|
||||
})
|
||||
console.log('配置已更新:', configManager.getAllConfig())
|
||||
}, 300)
|
||||
|
||||
// 处理单个配置项更改
|
||||
const handleConfigItemChange = (item: any) => {
|
||||
const config = configGroups.value.reduce((acc, group) => {
|
||||
group.items.forEach(item => {
|
||||
acc[item.key] = item.value
|
||||
const handleConfigItemChange = (item: any, group: ConfigGroup) => {
|
||||
configManager.updateConfig({
|
||||
[`${group.key}.${item.key}`]: item.value
|
||||
})
|
||||
return acc
|
||||
}, {} as Record<string, any>)
|
||||
|
||||
console.log('配置已更新:', config)
|
||||
console.log('配置已更新:', configManager.getAllConfig())
|
||||
}
|
||||
|
||||
// 处理配置组启用状态变更
|
||||
const handleGroupEnableChange = (group: ConfigGroup) => {
|
||||
const config = configGroups.value.reduce((acc, group) => {
|
||||
if (group.enabled) {
|
||||
group.items.forEach(item => {
|
||||
acc[item.key] = item.value
|
||||
configManager.updateConfig({
|
||||
[`${group.key}.enabled`]: group.enabled
|
||||
})
|
||||
}
|
||||
return acc
|
||||
}, {} as Record<string, any>)
|
||||
|
||||
console.log('配置已更新:', config)
|
||||
console.log('配置已更新:', configManager.getAllConfig())
|
||||
}
|
||||
|
||||
// 使用构造函数定义配置组
|
||||
const configGroups = ref([
|
||||
new ConfigGroup('appearance', '外观设置', false, [
|
||||
new TextConfigItem(
|
||||
'projectName',
|
||||
'项目名称',
|
||||
'设置新建项目时的默认项目名称',
|
||||
'',
|
||||
'请输入默认项目名称'
|
||||
),
|
||||
new SelectConfigItem(
|
||||
'theme',
|
||||
'主题',
|
||||
'切换应用的显示主题',
|
||||
[
|
||||
{ label: '浅色', value: 'light' },
|
||||
{ label: '深色', value: 'dark' }
|
||||
],
|
||||
'light'
|
||||
)
|
||||
]),
|
||||
|
||||
new ConfigGroup('system', '系统设置', true, [
|
||||
new SelectConfigItem(
|
||||
'language',
|
||||
'语言',
|
||||
'设置应用界面显示的语言',
|
||||
[
|
||||
{ label: '中文', value: 'zh-CN' },
|
||||
{ label: 'English', value: 'en-US' }
|
||||
],
|
||||
'zh-CN'
|
||||
),
|
||||
new SwitchConfigItem(
|
||||
'autoSave',
|
||||
'自动保存',
|
||||
'开启后将自动保存您的修改',
|
||||
true
|
||||
),
|
||||
new SwitchConfigItem(
|
||||
'notifications',
|
||||
'通知提醒',
|
||||
'是否显示系统通知提醒',
|
||||
true
|
||||
)
|
||||
])
|
||||
])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -129,7 +130,7 @@ const handleGroupEnableChange = (group: ConfigGroup) => {
|
||||
type="text"
|
||||
v-model="item.value"
|
||||
:placeholder="(item as any).placeholder"
|
||||
@change="handleConfigItemChange(item)"
|
||||
@input="handleTextConfigChange(item, group)"
|
||||
>
|
||||
</div>
|
||||
|
||||
@@ -138,7 +139,7 @@ const handleGroupEnableChange = (group: ConfigGroup) => {
|
||||
<input
|
||||
type="checkbox"
|
||||
v-model="item.value"
|
||||
@change="handleConfigItemChange(item)"
|
||||
@change="handleConfigItemChange(item, group)"
|
||||
>
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
@@ -147,7 +148,7 @@ const handleGroupEnableChange = (group: ConfigGroup) => {
|
||||
<div v-else-if="item.type === ConfigItemType.SELECT" class="select-wrapper">
|
||||
<select
|
||||
v-model="item.value"
|
||||
@change="handleConfigItemChange(item)"
|
||||
@change="handleConfigItemChange(item, group)"
|
||||
>
|
||||
<option
|
||||
v-for="option in (item as any).options"
|
||||
|
||||
@@ -5,44 +5,70 @@ export enum ConfigItemType {
|
||||
SELECT = 'select'
|
||||
}
|
||||
|
||||
// 配置项选项接口
|
||||
export interface ConfigOption {
|
||||
label: string
|
||||
value: string | number | boolean
|
||||
}
|
||||
|
||||
// 基础配置项接口
|
||||
export interface BaseConfigItem {
|
||||
type: ConfigItemType
|
||||
key: string
|
||||
label: string
|
||||
value: any
|
||||
description?: string // 配置项的详细说明
|
||||
description: string
|
||||
}
|
||||
|
||||
// 文本配置项
|
||||
export interface TextConfigItem extends BaseConfigItem {
|
||||
type: ConfigItemType.TEXT
|
||||
export class TextConfigItem implements BaseConfigItem {
|
||||
readonly type = ConfigItemType.TEXT
|
||||
value: string
|
||||
placeholder?: string
|
||||
|
||||
constructor(
|
||||
public key: string,
|
||||
public label: string,
|
||||
public description: string,
|
||||
defaultValue: string = '',
|
||||
public placeholder?: string
|
||||
) {
|
||||
this.value = defaultValue
|
||||
}
|
||||
}
|
||||
|
||||
// 开关配置项
|
||||
export interface SwitchConfigItem extends BaseConfigItem {
|
||||
type: ConfigItemType.SWITCH
|
||||
export class SwitchConfigItem implements BaseConfigItem {
|
||||
readonly type = ConfigItemType.SWITCH
|
||||
value: boolean
|
||||
|
||||
constructor(
|
||||
public key: string,
|
||||
public label: string,
|
||||
public description: string,
|
||||
defaultValue: boolean = false
|
||||
) {
|
||||
this.value = defaultValue
|
||||
}
|
||||
}
|
||||
|
||||
// 选择配置项
|
||||
export interface SelectConfigItem extends BaseConfigItem {
|
||||
type: ConfigItemType.SELECT
|
||||
export class SelectConfigItem implements BaseConfigItem {
|
||||
readonly type = ConfigItemType.SELECT
|
||||
value: string
|
||||
options: ConfigOption[]
|
||||
|
||||
constructor(
|
||||
public key: string,
|
||||
public label: string,
|
||||
public description: string,
|
||||
public options: Array<{ label: string; value: string }>,
|
||||
defaultValue: string
|
||||
) {
|
||||
this.value = defaultValue
|
||||
}
|
||||
}
|
||||
|
||||
// 配置项组
|
||||
export interface ConfigGroup {
|
||||
title: string
|
||||
enabled: boolean
|
||||
items: (TextConfigItem | SwitchConfigItem | SelectConfigItem)[]
|
||||
export type ConfigItem = TextConfigItem | SelectConfigItem | SwitchConfigItem
|
||||
|
||||
// 配置组
|
||||
export class ConfigGroup {
|
||||
constructor(
|
||||
public key: string,
|
||||
public title: string,
|
||||
public enabled: boolean,
|
||||
public items: ConfigItem[]
|
||||
) {}
|
||||
}
|
||||
98
src/utils/ConfigStore.ts
Normal file
98
src/utils/ConfigStore.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
// 配置存储接口
|
||||
export interface ConfigStore {
|
||||
get<T>(key: string): T | undefined
|
||||
set<T>(key: string, value: T): void
|
||||
getAll(): Record<string, any>
|
||||
clear(): void
|
||||
}
|
||||
|
||||
// 内存存储实现
|
||||
export class MemoryConfigStore implements ConfigStore {
|
||||
private store: Record<string, any> = {}
|
||||
|
||||
get<T>(key: string): T | undefined {
|
||||
return this.store[key] as T
|
||||
}
|
||||
|
||||
set<T>(key: string, value: T): void {
|
||||
this.store[key] = value
|
||||
}
|
||||
|
||||
getAll(): Record<string, any> {
|
||||
return { ...this.store }
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
this.store = {}
|
||||
}
|
||||
}
|
||||
|
||||
// LocalStorage存储实现
|
||||
export class LocalStorageConfigStore implements ConfigStore {
|
||||
private readonly prefix = 'app_config.'
|
||||
|
||||
private getKey(key: string): string {
|
||||
return this.prefix + key
|
||||
}
|
||||
|
||||
get<T>(key: string): T | undefined {
|
||||
const value = localStorage.getItem(this.getKey(key))
|
||||
return value ? JSON.parse(value) : undefined
|
||||
}
|
||||
|
||||
set<T>(key: string, value: T): void {
|
||||
localStorage.setItem(this.getKey(key), JSON.stringify(value))
|
||||
}
|
||||
|
||||
getAll(): Record<string, any> {
|
||||
const result: Record<string, any> = {}
|
||||
for (let i = 0; i < localStorage.length; i++) {
|
||||
const key = localStorage.key(i)
|
||||
if (key?.startsWith(this.prefix)) {
|
||||
const realKey = key.slice(this.prefix.length)
|
||||
result[realKey] = JSON.parse(localStorage.getItem(key) || '{}')
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
for (let i = localStorage.length - 1; i >= 0; i--) {
|
||||
const key = localStorage.key(i)
|
||||
if (key?.startsWith(this.prefix)) {
|
||||
localStorage.removeItem(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 配置管理器
|
||||
export class ConfigManager {
|
||||
private static instance: ConfigManager
|
||||
private store: ConfigStore
|
||||
|
||||
private constructor(store: ConfigStore) {
|
||||
this.store = store
|
||||
}
|
||||
|
||||
static getInstance(store: ConfigStore = new MemoryConfigStore()): ConfigManager {
|
||||
if (!ConfigManager.instance) {
|
||||
ConfigManager.instance = new ConfigManager(store)
|
||||
}
|
||||
return ConfigManager.instance
|
||||
}
|
||||
|
||||
updateConfig(config: Record<string, any>): void {
|
||||
Object.entries(config).forEach(([key, value]) => {
|
||||
this.store.set(key, value)
|
||||
})
|
||||
}
|
||||
|
||||
getConfig<T>(key: string): T | undefined {
|
||||
return this.store.get<T>(key)
|
||||
}
|
||||
|
||||
getAllConfig(): Record<string, any> {
|
||||
return this.store.getAll()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user