feat: add docker shell

This commit is contained in:
vben
2024-05-24 23:11:03 +08:00
parent d733987042
commit 38d58394e3
25 changed files with 394 additions and 120 deletions

View File

@@ -0,0 +1,3 @@
# @vben-core
系统一些比较基础的SDK和UI组件库请勿将任何业务逻辑和业务包放在这里。

View File

@@ -91,6 +91,8 @@ interface Preference {
pageTransitionEnable: boolean;
/** 是否开启半深色菜单只在theme='light'时生效) */
semiDarkMenu: boolean;
/** 是否显示偏好设置 */
showPreference: boolean;
/** 侧边栏是否折叠 */
sideCollapse: boolean;
/** 侧边栏折叠时是否显示title */

View File

@@ -80,6 +80,33 @@ type MaybeReadonlyRef<T> = (() => T) | ComputedRef<T>;
*/
type MaybeComputedRef<T> = MaybeReadonlyRef<T> | MaybeRef<T>;
type Merge<O extends object, T extends object> = {
[K in keyof O | keyof T]: K extends keyof T
? T[K]
: K extends keyof O
? O[K]
: never;
};
/**
* T = [
* { name: string; age: number; },
* { sex: 'male' | 'female'; age: string }
* ]
* =>
* MergeAll<T> = {
* name: string;
* sex: 'male' | 'female';
* age: string
* }
*/
type MergeAll<
T extends object[],
R extends object = Record<string, any>,
> = T extends [infer F extends object, ...infer Rest extends object[]]
? MergeAll<Rest, Merge<R, F>>
: R;
export {
type AnyFunction,
type AnyNormalFunction,
@@ -89,6 +116,8 @@ export {
type IntervalHandle,
type MaybeComputedRef,
type MaybeReadonlyRef,
type Merge,
type MergeAll,
type NonNullable,
type Nullable,
type ReadonlyRecordable,

View File

@@ -22,6 +22,6 @@ const delegatedProps = computed(() => {
<template>
<DropdownMenuSeparator
v-bind="delegatedProps"
:class="cn('bg-muted -mx-1 my-1 h-px', props.class)"
:class="cn('bg-border -mx-1 my-1 h-px', props.class)"
/>
</template>

View File

@@ -14,7 +14,7 @@ import {
import { $t } from '@vben/locales';
import { preference, resetPreference, usePreference } from '@vben/preference';
import { useClipboard } from '@vueuse/core';
import { computed, ref } from 'vue';
import { computed } from 'vue';
import {
Animation,
@@ -33,6 +33,7 @@ import {
ThemeColor,
} from './blocks';
import Trigger from './trigger.vue';
import { useOpenPreference } from './use-open-preference';
withDefaults(defineProps<{ colorPrimaryPresets: string[] }>(), {
colorPrimaryPresets: () => [],
@@ -106,11 +107,7 @@ const showBreadcrumbConfig = computed(() => {
);
});
const openSheet = ref(false);
function handlerOpenSheet() {
openSheet.value = true;
}
const { openPreference } = useOpenPreference();
async function handleCopy() {
await copy(JSON.stringify(diffPreference.value, null, 2));
@@ -130,11 +127,12 @@ function handleReset() {
<template>
<div class="z-100 fixed right-0 top-1/3">
<VbenSheet
v-model:open="openPreference"
:description="$t('preference.preferences-subtitle')"
:title="$t('preference.preferences')"
>
<template #trigger>
<Trigger @click="handlerOpenSheet" />
<Trigger />
</template>
<template #extra>
<VbenIconButton

View File

@@ -0,0 +1,16 @@
import { ref } from 'vue';
const openPreference = ref(false);
function useOpenPreference() {
function handleOpenPreference() {
openPreference.value = true;
}
return {
handleOpenPreference,
openPreference,
};
}
export { useOpenPreference };

View File

@@ -1,5 +1,7 @@
<script setup lang="ts">
import { IcRoundLogout } from '@vben-core/iconify';
import type { AnyFunction } from '@vben/types';
import { IcRoundLogout, IcRoundSettingsSuggest } from '@vben-core/iconify';
import {
Badge,
DropdownMenu,
@@ -16,9 +18,11 @@ import {
import type { Component } from 'vue';
import { $t } from '@vben/locales';
import { AnyFunction } from '@vben/types';
import { preference } from '@vben/preference';
import { ref } from 'vue';
import { useOpenPreference } from '../preference/use-open-preference';
interface Props {
/**
* 头像
@@ -59,6 +63,8 @@ const emit = defineEmits<{ logout: [] }>();
const openPopover = ref(false);
const openDialog = ref(false);
const { handleOpenPreference } = useOpenPreference();
function handleLogout() {
// emit
openDialog.value = true;
@@ -90,8 +96,8 @@ function handleSubmitLogout() {
</div>
</div>
</DropdownMenuTrigger>
<DropdownMenuContent class="mr-2 min-w-[240px] p-0">
<DropdownMenuLabel class="border-border flex items-center border-b p-3">
<DropdownMenuContent class="mr-2 min-w-[240px] p-0 pb-1">
<DropdownMenuLabel class="flex items-center p-3">
<VbenAvatar
:alt="text"
:src="avatar"
@@ -117,22 +123,28 @@ function handleSubmitLogout() {
<DropdownMenuItem
v-for="menu in menus"
:key="menu.text"
class="mx-1 rounded-sm py-2.5"
class="lineh mx-1 flex cursor-pointer items-center rounded-sm py-1 leading-8"
@click="menu.handler"
>
<VbenIcon :icon="menu.icon" class="mr-2 size-4" />
<VbenIcon :icon="menu.icon" class="mr-2 size-5" />
{{ menu.text }}
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem class="w-full p-0">
<div
class="border-border flex-center hover:bg-accent hover:text-accent-foreground h-10 w-full cursor-pointer border-t"
@click="handleLogout"
>
<IcRoundLogout class="mr-2" />
{{ $t('common.logout') }}
</div>
<DropdownMenuItem
v-if="preference"
class="mx-1 flex cursor-pointer items-center rounded-sm py-1 leading-8"
@click="handleOpenPreference"
>
<IcRoundSettingsSuggest class="mr-2 size-5" />
{{ $t('preference.preferences') }}
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
class="mx-1 flex cursor-pointer items-center rounded-sm py-1 leading-8"
@click="handleLogout"
>
<IcRoundLogout class="mr-2 size-5" />
{{ $t('common.logout') }}
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>

View File

@@ -127,7 +127,7 @@ function wrapperMenus(menus: MenuRecordRaw[]) {
(value: boolean) => updatePreference('sideExpandOnHover', value)
"
>
<template #preference>
<template v-if="preference.showPreference" #preference>
<PreferenceWidget />
</template>

View File

@@ -2,7 +2,7 @@ import type { Preference } from '@vben-core/typings';
class PreferenceCache {
cachePrefix: string;
constructor(cachePrefix: string = 'vben-admin') {
constructor(cachePrefix: string) {
this.cachePrefix = cachePrefix;
}
@@ -24,8 +24,7 @@ class PreferenceCache {
* 获取偏好设置的缓存键
*/
getCacheKey(name: string = 'preference') {
const env = import.meta.env.DEV ? 'dev' : 'prod';
return `__${this.cachePrefix}-${name}-${env}__`;
return `__${this.cachePrefix}-${name}__`;
}
/**

View File

@@ -34,8 +34,9 @@ const defaultPreference: Preference = {
pageTransition: 'fade-slide',
pageTransitionEnable: true,
semiDarkMenu: true,
showPreference: true,
sideCollapse: false,
sideCollapseShowTitle: false,
sideCollapseShowTitle: true,
sideExpandOnHover: true,
sideExtraCollapse: true,
sideVisible: true,

View File

@@ -4,22 +4,24 @@ import { PreferenceCache } from './cache';
import { overridesPreference } from './preference';
interface SetupPreferenceOptions {
/**
* @zh_CN 环境
*/
env: string;
/**
* @zh_CN 应用名,由于 @vben/preference 是公用的后续可能有多个app为了防止多个app缓存冲突可在这里配置应用名
* 应用名将被用于持久化的前缀
*/
cachePrefix?: string;
namespace: string;
/**
* @zh_CN app自行覆盖偏好设置
*/
overrides?: DeepPartial<Preference>;
}
async function setupPreference(options: SetupPreferenceOptions = {}) {
const { cachePrefix = 'vben-admin-pro', overrides = {} } = options;
const cache = new PreferenceCache(cachePrefix);
async function setupPreference(options: SetupPreferenceOptions) {
const { env, namespace, overrides = {} } = options;
const cache = new PreferenceCache(`${namespace}-${env}`);
overridesPreference(overrides, cache);
}

View File

@@ -3,26 +3,29 @@ import type { App } from 'vue';
import { createPinia } from 'pinia';
interface SetupStoreOptions {
/**
* @zh_CN 环境
*/
env: string;
/**
* @zh_CN 应用名,由于 @vben/stores 是公用的后续可能有多个app为了防止多个app缓存冲突可在这里配置应用名
* 应用名将被用于持久化的前缀
*/
cachePrefix?: string;
namespace: string;
}
/**
* @zh_CN 初始化pinia
* @param app vue app 实例
*/
async function setupStore(app: App, options: SetupStoreOptions = {}) {
async function setupStore(app: App, options: SetupStoreOptions) {
const { createPersistedState } = await import('pinia-plugin-persistedstate');
const pinia = createPinia();
const { cachePrefix = 'vben-admin-pro' } = options;
const env = import.meta.env.DEV ? 'dev' : 'prod';
const { env, namespace } = options;
pinia.use(
createPersistedState({
// key $appName-$store.id
key: (storeKey) => `__${cachePrefix}-${storeKey}-${env}__`,
key: (storeKey) => `__${namespace}-${env}-${storeKey}__`,
storage: localStorage,
}),
);

View File

@@ -19,9 +19,6 @@
"files": [
"dist"
],
"sideEffects": [
"**/*.css"
],
"main": "./dist/index.mjs",
"module": "./dist/index.mjs",
"imports": {
@@ -42,6 +39,10 @@
}
}
},
"peerDependencies": {
"@vben-core/design": "workspace:*",
"@vben-core/design-tokens": "workspace:*"
},
"dependencies": {
"@vben-core/design": "workspace:*",
"@vben-core/design-tokens": "workspace:*"