36 changed files with 256 additions and 612 deletions
@ -0,0 +1,34 @@ |
|||||
|
{ |
||||
|
"page": { |
||||
|
"demos": { |
||||
|
"title": "Demos", |
||||
|
"access": { |
||||
|
"title": "Access Control", |
||||
|
"frontend-control": "Front-end Control", |
||||
|
"backend-control": "Backend Control", |
||||
|
"page": "Page visit", |
||||
|
"button": "Button control", |
||||
|
"loading-menu": "In the loading menu", |
||||
|
"access-test-1": "Super visit", |
||||
|
"access-test-2": "Admin visit", |
||||
|
"access-test-3": "User visit" |
||||
|
}, |
||||
|
"nested": { |
||||
|
"title": "Nested Menu", |
||||
|
"menu1": "Menu 1", |
||||
|
"menu2": "Menu 2", |
||||
|
"menu21": "Menu 2-1", |
||||
|
"menu3": "Menu 3", |
||||
|
"menu31": "Menu 3-1", |
||||
|
"menu32": "Menu 3-2", |
||||
|
"menu321": "Menu 3-2-1" |
||||
|
}, |
||||
|
"outside": { |
||||
|
"title": "External Page", |
||||
|
"embedded": "embedded Page", |
||||
|
"external-link": "External Link" |
||||
|
}, |
||||
|
"fallback": { "title": "Fallback Page" } |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,28 +0,0 @@ |
|||||
page: |
|
||||
demos: |
|
||||
title: Demos |
|
||||
access: |
|
||||
title: Access Control |
|
||||
frontend-control: Front-end Control |
|
||||
backend-control: Backend Control |
|
||||
page: Page visit |
|
||||
button: Button control |
|
||||
loading-menu: In the loading menu |
|
||||
access-test-1: Super visit |
|
||||
access-test-2: Admin visit |
|
||||
access-test-3: User visit |
|
||||
nested: |
|
||||
title: Nested Menu |
|
||||
menu1: Menu 1 |
|
||||
menu2: Menu 2 |
|
||||
menu21: Menu 2-1 |
|
||||
menu3: Menu 3 |
|
||||
menu31: Menu 3-1 |
|
||||
menu32: Menu 3-2 |
|
||||
menu321: Menu 3-2-1 |
|
||||
outside: |
|
||||
title: External Page |
|
||||
embedded: embedded Page |
|
||||
external-link: External Link |
|
||||
fallback: |
|
||||
title: Fallback Page |
|
||||
@ -0,0 +1,35 @@ |
|||||
|
{ |
||||
|
"page": { |
||||
|
"demos": { |
||||
|
"title": "演示", |
||||
|
"access": { |
||||
|
"title": "访问控制", |
||||
|
"frontend-control": "前端控制", |
||||
|
"backend-control": "后端控制", |
||||
|
"page": "页面访问", |
||||
|
"button": "按钮控制", |
||||
|
"access-test-1": "Super 可见", |
||||
|
"access-test-2": "Admin 可见", |
||||
|
"access-test-3": "User 可见" |
||||
|
}, |
||||
|
"nested": { |
||||
|
"title": "嵌套菜单", |
||||
|
"menu1": "菜单 1", |
||||
|
"menu2": "菜单 2", |
||||
|
"menu21": "菜单 2-1", |
||||
|
"menu3": "菜单 3", |
||||
|
"menu31": "菜单 3-1", |
||||
|
"menu32": "菜单 3-2", |
||||
|
"menu321": "菜单 3-2-1" |
||||
|
}, |
||||
|
"outside": { |
||||
|
"title": "外部页面", |
||||
|
"embedded": "内嵌", |
||||
|
"external-link": "外链" |
||||
|
}, |
||||
|
"fallback": { |
||||
|
"title": "缺省页" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,27 +0,0 @@ |
|||||
page: |
|
||||
demos: |
|
||||
title: 演示 |
|
||||
access: |
|
||||
title: 访问控制 |
|
||||
frontend-control: 前端控制 |
|
||||
backend-control: 后端控制 |
|
||||
page: 页面访问 |
|
||||
button: 按钮控制 |
|
||||
access-test-1: Super 可见 |
|
||||
access-test-2: Admin 可见 |
|
||||
access-test-3: User 可见 |
|
||||
nested: |
|
||||
title: 嵌套菜单 |
|
||||
menu1: 菜单 1 |
|
||||
menu2: 菜单 2 |
|
||||
menu21: 菜单 2-1 |
|
||||
menu3: 菜单 3 |
|
||||
menu31: 菜单 3-1 |
|
||||
menu32: 菜单 3-2 |
|
||||
menu321: 菜单 3-2-1 |
|
||||
outside: |
|
||||
title: 外部页面 |
|
||||
embedded: 内嵌 |
|
||||
external-link: 外链 |
|
||||
fallback: |
|
||||
title: 缺省页 |
|
||||
@ -1,8 +1,9 @@ |
|||||
import type { DeepPartial } from '@vben/types'; |
import { defineOverridesPreferences } from '@vben-core/preferences'; |
||||
import type { Preferences } from '@vben-core/preferences'; |
|
||||
|
|
||||
/** |
/** |
||||
* @description 项目配置文件 |
* @description 项目配置文件 |
||||
* 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置 |
* 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置 |
||||
*/ |
*/ |
||||
export const overridesPreferences: DeepPartial<Preferences> = {}; |
export const overridesPreferences = defineOverridesPreferences({ |
||||
|
// overrides
|
||||
|
}); |
||||
|
|||||
@ -1,132 +0,0 @@ |
|||||
import { describe, expect, it } from 'vitest'; |
|
||||
|
|
||||
import { flattenObject } from './flatten-object'; |
|
||||
|
|
||||
describe('flattenObject', () => { |
|
||||
it('should flatten a nested object correctly', () => { |
|
||||
const nestedObject = { |
|
||||
language: 'en', |
|
||||
notifications: { |
|
||||
email: true, |
|
||||
push: { |
|
||||
sound: true, |
|
||||
vibration: false, |
|
||||
}, |
|
||||
}, |
|
||||
theme: 'light', |
|
||||
}; |
|
||||
|
|
||||
const expected = { |
|
||||
language: 'en', |
|
||||
notificationsEmail: true, |
|
||||
notificationsPushSound: true, |
|
||||
notificationsPushVibration: false, |
|
||||
theme: 'light', |
|
||||
}; |
|
||||
|
|
||||
const result = flattenObject(nestedObject); |
|
||||
expect(result).toEqual(expected); |
|
||||
}); |
|
||||
|
|
||||
it('should handle empty objects', () => { |
|
||||
const nestedObject = {}; |
|
||||
const expected = {}; |
|
||||
|
|
||||
const result = flattenObject(nestedObject); |
|
||||
expect(result).toEqual(expected); |
|
||||
}); |
|
||||
|
|
||||
it('should handle objects with primitive values', () => { |
|
||||
const nestedObject = { |
|
||||
active: true, |
|
||||
age: 30, |
|
||||
name: 'Alice', |
|
||||
}; |
|
||||
|
|
||||
const expected = { |
|
||||
active: true, |
|
||||
age: 30, |
|
||||
name: 'Alice', |
|
||||
}; |
|
||||
|
|
||||
const result = flattenObject(nestedObject); |
|
||||
expect(result).toEqual(expected); |
|
||||
}); |
|
||||
|
|
||||
it('should handle objects with null values', () => { |
|
||||
const nestedObject = { |
|
||||
user: { |
|
||||
age: null, |
|
||||
name: null, |
|
||||
}, |
|
||||
}; |
|
||||
|
|
||||
const expected = { |
|
||||
userAge: null, |
|
||||
userName: null, |
|
||||
}; |
|
||||
|
|
||||
const result = flattenObject(nestedObject); |
|
||||
expect(result).toEqual(expected); |
|
||||
}); |
|
||||
|
|
||||
it('should handle nested empty objects', () => { |
|
||||
const nestedObject = { |
|
||||
a: {}, |
|
||||
b: { c: {} }, |
|
||||
}; |
|
||||
|
|
||||
const expected = {}; |
|
||||
|
|
||||
const result = flattenObject(nestedObject); |
|
||||
expect(result).toEqual(expected); |
|
||||
}); |
|
||||
|
|
||||
it('should handle arrays within objects', () => { |
|
||||
const nestedObject = { |
|
||||
hobbies: ['reading', 'gaming'], |
|
||||
name: 'Alice', |
|
||||
}; |
|
||||
|
|
||||
const expected = { |
|
||||
hobbies: ['reading', 'gaming'], |
|
||||
name: 'Alice', |
|
||||
}; |
|
||||
|
|
||||
const result = flattenObject(nestedObject); |
|
||||
expect(result).toEqual(expected); |
|
||||
}); |
|
||||
it('should flatten objects with nested arrays correctly', () => { |
|
||||
const nestedObject = { |
|
||||
person: { |
|
||||
hobbies: ['reading', 'gaming'], |
|
||||
name: 'Alice', |
|
||||
}, |
|
||||
}; |
|
||||
|
|
||||
const expected = { |
|
||||
personHobbies: ['reading', 'gaming'], |
|
||||
personName: 'Alice', |
|
||||
}; |
|
||||
|
|
||||
const result = flattenObject(nestedObject); |
|
||||
expect(result).toEqual(expected); |
|
||||
}); |
|
||||
|
|
||||
it('should handle objects with undefined values', () => { |
|
||||
const nestedObject = { |
|
||||
user: { |
|
||||
age: undefined, |
|
||||
name: 'Alice', |
|
||||
}, |
|
||||
}; |
|
||||
|
|
||||
const expected = { |
|
||||
userAge: undefined, |
|
||||
userName: 'Alice', |
|
||||
}; |
|
||||
|
|
||||
const result = flattenObject(nestedObject); |
|
||||
expect(result).toEqual(expected); |
|
||||
}); |
|
||||
}); |
|
||||
@ -1,82 +0,0 @@ |
|||||
import type { Flatten } from '@vben-core/typings'; |
|
||||
|
|
||||
import { capitalizeFirstLetter } from '@vben-core/toolkit'; |
|
||||
|
|
||||
/** |
|
||||
* 将嵌套对象扁平化 |
|
||||
* @param obj - 需要扁平化的对象 |
|
||||
* @param parentKey - 父键名,用于递归时拼接键名 |
|
||||
* @param result - 存储结果的对象 |
|
||||
* @returns 扁平化后的对象 |
|
||||
* |
|
||||
* 示例: |
|
||||
* const nestedObj = { |
|
||||
* user: { |
|
||||
* name: 'Alice', |
|
||||
* address: { |
|
||||
* city: 'Wonderland', |
|
||||
* zip: '12345' |
|
||||
* } |
|
||||
* }, |
|
||||
* items: [ |
|
||||
* { id: 1, name: 'Item 1' }, |
|
||||
* { id: 2, name: 'Item 2' } |
|
||||
* ], |
|
||||
* active: true |
|
||||
* }; |
|
||||
* const flatObj = flattenObject(nestedObj); |
|
||||
* console.log(flatObj); |
|
||||
* 输出: |
|
||||
* { |
|
||||
* userName: 'Alice', |
|
||||
* userAddressCity: 'Wonderland', |
|
||||
* userAddressZip: '12345', |
|
||||
* items: [ { id: 1, name: 'Item 1' }, { id: 2, name: 'Item 2' } ], |
|
||||
* active: true |
|
||||
* } |
|
||||
*/ |
|
||||
function flattenObject<T extends Record<string, any>>( |
|
||||
obj: T, |
|
||||
parentKey: string = '', |
|
||||
result: Record<string, any> = {}, |
|
||||
): Flatten<T> { |
|
||||
Object.keys(obj).forEach((key) => { |
|
||||
const newKey = parentKey |
|
||||
? `${parentKey}${capitalizeFirstLetter(key)}` |
|
||||
: key; |
|
||||
const value = obj[key]; |
|
||||
|
|
||||
if (value && typeof value === 'object' && !Array.isArray(value)) { |
|
||||
flattenObject(value, newKey, result); |
|
||||
} else { |
|
||||
result[newKey] = value; |
|
||||
} |
|
||||
}); |
|
||||
return result as Flatten<T>; |
|
||||
} |
|
||||
|
|
||||
export { flattenObject }; |
|
||||
|
|
||||
// 定义递归类型,用于推断扁平化后的对象类型
|
|
||||
// 限制递归深度的辅助类型
|
|
||||
// type FlattenDepth<
|
|
||||
// T,
|
|
||||
// Depth extends number,
|
|
||||
// CurrentDepth extends number[] = [],
|
|
||||
// > = {
|
|
||||
// [K in keyof T as CurrentDepth['length'] extends Depth
|
|
||||
// ? K
|
|
||||
// : T[K] extends object
|
|
||||
// ? `${CurrentDepth['length'] extends 0 ? UnCapitalize<K & string> : Capitalize<K & string>}${keyof FlattenDepth<T[K], Depth, [...CurrentDepth, 1]> extends string ? Capitalize<keyof FlattenDepth<T[K], Depth, [...CurrentDepth, 1]>> : ''}`
|
|
||||
// : `${CurrentDepth['length'] extends 0 ? UnCapitalize<K & string> : Capitalize<K & string>}`]: CurrentDepth['length'] extends Depth
|
|
||||
// ? T[K]
|
|
||||
// : T[K] extends object
|
|
||||
// ? FlattenDepth<T[K], Depth, [...CurrentDepth, 1]>[keyof FlattenDepth<
|
|
||||
// T[K],
|
|
||||
// Depth,
|
|
||||
// [...CurrentDepth, 1]
|
|
||||
// >]
|
|
||||
// : T[K];
|
|
||||
// };
|
|
||||
|
|
||||
// type Flatten<T, Depth extends number = 4> = FlattenDepth<T, Depth>;
|
|
||||
@ -1,115 +0,0 @@ |
|||||
import { describe, expect, it } from 'vitest'; |
|
||||
|
|
||||
import { nestedObject } from './nested-object'; |
|
||||
|
|
||||
describe('nestedObject', () => { |
|
||||
it('should convert flat object to nested object with level 1', () => { |
|
||||
const flatObject = { |
|
||||
anotherKeyExample: 2, |
|
||||
commonAppName: 1, |
|
||||
someOtherKey: 3, |
|
||||
}; |
|
||||
|
|
||||
const expectedNestedObject = { |
|
||||
anotherKeyExample: 2, |
|
||||
commonAppName: 1, |
|
||||
someOtherKey: 3, |
|
||||
}; |
|
||||
|
|
||||
expect(nestedObject(flatObject, 1)).toEqual(expectedNestedObject); |
|
||||
}); |
|
||||
|
|
||||
it('should convert flat object to nested object with level 2', () => { |
|
||||
const flatObject = { |
|
||||
appAnotherKeyExample: 2, |
|
||||
appCommonName: 1, |
|
||||
appSomeOtherKey: 3, |
|
||||
}; |
|
||||
|
|
||||
const expectedNestedObject = { |
|
||||
app: { |
|
||||
anotherKeyExample: 2, |
|
||||
commonName: 1, |
|
||||
someOtherKey: 3, |
|
||||
}, |
|
||||
}; |
|
||||
|
|
||||
expect(nestedObject(flatObject, 2)).toEqual(expectedNestedObject); |
|
||||
}); |
|
||||
|
|
||||
it('should convert flat object to nested object with level 3', () => { |
|
||||
const flatObject = { |
|
||||
appAnotherKeyExampleValue: 2, |
|
||||
appCommonNameKey: 1, |
|
||||
appSomeOtherKeyItem: 3, |
|
||||
}; |
|
||||
|
|
||||
const expectedNestedObject = { |
|
||||
app: { |
|
||||
another: { |
|
||||
keyExampleValue: 2, |
|
||||
}, |
|
||||
common: { |
|
||||
nameKey: 1, |
|
||||
}, |
|
||||
some: { |
|
||||
otherKeyItem: 3, |
|
||||
}, |
|
||||
}, |
|
||||
}; |
|
||||
|
|
||||
expect(nestedObject(flatObject, 3)).toEqual(expectedNestedObject); |
|
||||
}); |
|
||||
|
|
||||
it('should handle empty object', () => { |
|
||||
const flatObject = {}; |
|
||||
|
|
||||
const expectedNestedObject = {}; |
|
||||
|
|
||||
expect(nestedObject(flatObject, 1)).toEqual(expectedNestedObject); |
|
||||
}); |
|
||||
|
|
||||
it('should handle single key object', () => { |
|
||||
const flatObject = { |
|
||||
singleKey: 1, |
|
||||
}; |
|
||||
|
|
||||
const expectedNestedObject = { |
|
||||
singleKey: 1, |
|
||||
}; |
|
||||
|
|
||||
expect(nestedObject(flatObject, 1)).toEqual(expectedNestedObject); |
|
||||
}); |
|
||||
|
|
||||
it('should handle complex keys', () => { |
|
||||
const flatObject = { |
|
||||
anotherComplexKeyWithParts: 2, |
|
||||
complexKeyWithMultipleParts: 1, |
|
||||
}; |
|
||||
|
|
||||
const expectedNestedObject = { |
|
||||
anotherComplexKeyWithParts: 2, |
|
||||
complexKeyWithMultipleParts: 1, |
|
||||
}; |
|
||||
|
|
||||
expect(nestedObject(flatObject, 1)).toEqual(expectedNestedObject); |
|
||||
}); |
|
||||
|
|
||||
it('should correctly nest an object based on the specified level', () => { |
|
||||
const obj = { |
|
||||
oneFiveSix: 'Value156', |
|
||||
oneTwoFour: 'Value124', |
|
||||
oneTwoThree: 'Value123', |
|
||||
}; |
|
||||
|
|
||||
const nested = nestedObject(obj, 2); |
|
||||
|
|
||||
expect(nested).toEqual({ |
|
||||
one: { |
|
||||
fiveSix: 'Value156', |
|
||||
twoFour: 'Value124', |
|
||||
twoThree: 'Value123', |
|
||||
}, |
|
||||
}); |
|
||||
}); |
|
||||
}); |
|
||||
@ -1,70 +0,0 @@ |
|||||
import { toLowerCaseFirstLetter } from '@vben-core/toolkit'; |
|
||||
|
|
||||
/** |
|
||||
* 将扁平对象转换为嵌套对象。 |
|
||||
* |
|
||||
* @template T - 输入对象值的类型 |
|
||||
* @param {Record<string, T>} obj - 要转换的扁平对象 |
|
||||
* @param {number} level - 嵌套的层级 |
|
||||
* @returns {T} 嵌套对象 |
|
||||
* |
|
||||
* @example |
|
||||
* 将扁平对象转换为嵌套对象,嵌套层级为 1 |
|
||||
* const flatObject = { |
|
||||
* 'commonAppName': 1, |
|
||||
* 'anotherKeyExample': 2, |
|
||||
* 'someOtherKey': 3 |
|
||||
* }; |
|
||||
* const nestedObject = nestedObject(flatObject, 1); |
|
||||
* console.log(nestedObject); |
|
||||
* 输出: |
|
||||
* { |
|
||||
* commonAppName: 1, |
|
||||
* anotherKeyExample: 2, |
|
||||
* someOtherKey: 3 |
|
||||
* } |
|
||||
* |
|
||||
* @example |
|
||||
* 将扁平对象转换为嵌套对象,嵌套层级为 2 |
|
||||
* const flatObject = { |
|
||||
* 'appCommonName': 1, |
|
||||
* 'appAnotherKeyExample': 2, |
|
||||
* 'appSomeOtherKey': 3 |
|
||||
* }; |
|
||||
* const nestedObject = nestedObject(flatObject, 2); |
|
||||
* console.log(nestedObject); |
|
||||
* 输出: |
|
||||
* { |
|
||||
* app: { |
|
||||
* commonName: 1, |
|
||||
* anotherKeyExample: 2, |
|
||||
* someOtherKey: 3 |
|
||||
* } |
|
||||
* } |
|
||||
*/ |
|
||||
|
|
||||
function nestedObject<T>(obj: Record<string, T>, level: number): T { |
|
||||
const result: any = {}; |
|
||||
|
|
||||
for (const key in obj) { |
|
||||
const keys = key.split(/(?=[A-Z])/); |
|
||||
// 将驼峰式分割为数组;
|
|
||||
let current = result; |
|
||||
|
|
||||
for (let i = 0; i < keys.length; i++) { |
|
||||
const lowerKey = keys[i].toLowerCase(); |
|
||||
if (i === level - 1) { |
|
||||
const remainingKeys = keys.slice(i).join(''); // 保留后续部分作为键的一部分
|
|
||||
current[toLowerCaseFirstLetter(remainingKeys)] = obj[key]; |
|
||||
break; |
|
||||
} else { |
|
||||
current[lowerKey] = current[lowerKey] || {}; |
|
||||
current = current[lowerKey]; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return result as T; |
|
||||
} |
|
||||
|
|
||||
export { nestedObject }; |
|
||||
@ -1,40 +0,0 @@ |
|||||
// `Prev` 类型用于表示递归深度的递减。它是一个元组,其索引代表了递归的层数,通过索引访问可以得到减少后的层数。
|
|
||||
// 例如,Prev[3] 等于 2,表示递归深度从 3 减少到 2。
|
|
||||
type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...0[]]; |
|
||||
|
|
||||
// `FlattenDepth` 类型用于将一个嵌套的对象类型“展平”,同时考虑到了递归的深度。
|
|
||||
// 它接受三个泛型参数:T(要处理的类型),Prefix(属性名前缀,默认为空字符串),Depth(递归深度,默认为3)。
|
|
||||
// 如果当前深度(Depth)为 0,则停止递归并返回 `never`。否则,如果属性值是对象类型,则递归调用 `FlattenDepth` 并递减深度。
|
|
||||
// 对于非对象类型的属性,将其直接映射到结果类型中,并根据前缀构造属性名。
|
|
||||
|
|
||||
type FlattenDepth<T, Prefix extends string = '', Depth extends number = 4> = { |
|
||||
[K in keyof T]: T[K] extends object |
|
||||
? Depth extends 0 |
|
||||
? never |
|
||||
: FlattenDepth< |
|
||||
T[K], |
|
||||
`${Prefix}${K extends string ? (Prefix extends '' ? K : Capitalize<K>) : ''}`, |
|
||||
Prev[Depth] |
|
||||
> |
|
||||
: { |
|
||||
[P in `${Prefix}${K extends string ? (Prefix extends '' ? K : Capitalize<K>) : ''}`]: T[K]; |
|
||||
}; |
|
||||
}[keyof T] extends infer O |
|
||||
? { [P in keyof O]: O[P] } |
|
||||
: never; |
|
||||
|
|
||||
// `UnionToIntersection` 类型用于将一个联合类型转换为交叉类型。
|
|
||||
// 这个类型通过条件类型和类型推断的方式来实现。它先尝试将输入类型(U)映射为一个函数类型,
|
|
||||
// 然后通过推断这个函数类型的返回类型(infer I),最终得到一个交叉类型。
|
|
||||
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ( |
|
||||
k: infer I, |
|
||||
) => void |
|
||||
? I |
|
||||
: never; |
|
||||
|
|
||||
type Flatten<T> = UnionToIntersection<FlattenDepth<T>>; |
|
||||
|
|
||||
type FlattenObject<T> = FlattenDepth<T>; |
|
||||
type FlattenObjectKeys<T> = keyof FlattenObject<T>; |
|
||||
|
|
||||
export type { Flatten, FlattenObject, FlattenObjectKeys, UnionToIntersection }; |
|
||||
@ -1,5 +1,5 @@ |
|||||
export { default as CodeAuthority } from './code-authority.vue'; |
export { default as CodeAccess } from './code-access.vue'; |
||||
export * from './generate-menu-and-routes'; |
export * from './generate-menu-and-routes'; |
||||
export { default as RoleAuthority } from './role-authority.vue'; |
export { default as RoleAccess } from './role-access.vue'; |
||||
export type * from './types'; |
export type * from './types'; |
||||
export * from './use-access'; |
export * from './use-access'; |
||||
|
|||||
@ -1,21 +0,0 @@ |
|||||
<script setup lang="ts"> |
|
||||
import { $t } from '@vben-core/locales'; |
|
||||
|
|
||||
import SwitchItem from '../switch-item.vue'; |
|
||||
|
|
||||
defineOptions({ |
|
||||
name: 'PreferenceInterfaceControl', |
|
||||
}); |
|
||||
|
|
||||
const tabsVisible = defineModel<boolean>('tabsVisible'); |
|
||||
const logoVisible = defineModel<boolean>('logoVisible'); |
|
||||
</script> |
|
||||
|
|
||||
<template> |
|
||||
<SwitchItem v-model="tabsVisible"> |
|
||||
{{ $t('preferences.tabbar.enable') }} |
|
||||
</SwitchItem> |
|
||||
<SwitchItem v-model="logoVisible"> |
|
||||
{{ $t('preferences.logo-visible') }} |
|
||||
</SwitchItem> |
|
||||
</template> |
|
||||
@ -0,0 +1,41 @@ |
|||||
|
<script setup lang="ts"> |
||||
|
import { $t } from '@vben-core/locales'; |
||||
|
|
||||
|
import SwitchItem from '../switch-item.vue'; |
||||
|
|
||||
|
defineOptions({ |
||||
|
name: 'PreferenceInterfaceControl', |
||||
|
}); |
||||
|
|
||||
|
const widgetGlobalSearch = defineModel<boolean>('widgetGlobalSearch'); |
||||
|
const widgetFullscreen = defineModel<boolean>('widgetFullscreen'); |
||||
|
const widgetLanguageToggle = defineModel<boolean>('widgetLanguageToggle'); |
||||
|
const widgetNotification = defineModel<boolean>('widgetNotification'); |
||||
|
const widgetThemeToggle = defineModel<boolean>('widgetThemeToggle'); |
||||
|
const widgetAiAssistant = defineModel<boolean>('widgetAiAssistant'); |
||||
|
const widgetSidebarToggle = defineModel<boolean>('widgetSidebarToggle'); |
||||
|
</script> |
||||
|
|
||||
|
<template> |
||||
|
<SwitchItem v-model="widgetGlobalSearch"> |
||||
|
{{ $t('preferences.widget.global-search') }} |
||||
|
</SwitchItem> |
||||
|
<SwitchItem v-model="widgetThemeToggle"> |
||||
|
{{ $t('preferences.widget.theme-toggle') }} |
||||
|
</SwitchItem> |
||||
|
<SwitchItem v-model="widgetLanguageToggle"> |
||||
|
{{ $t('preferences.widget.language-toggle') }} |
||||
|
</SwitchItem> |
||||
|
<SwitchItem v-model="widgetFullscreen"> |
||||
|
{{ $t('preferences.widget.fullscreen') }} |
||||
|
</SwitchItem> |
||||
|
<SwitchItem v-model="widgetNotification"> |
||||
|
{{ $t('preferences.widget.notification') }} |
||||
|
</SwitchItem> |
||||
|
<SwitchItem v-model="widgetAiAssistant"> |
||||
|
{{ $t('preferences.widget.ai-assistant') }} |
||||
|
</SwitchItem> |
||||
|
<SwitchItem v-model="widgetSidebarToggle"> |
||||
|
{{ $t('preferences.widget.sidebar-toggle') }} |
||||
|
</SwitchItem> |
||||
|
</template> |
||||
Loading…
Reference in new issue