style(projects): format code
This commit is contained in:
@ -3,7 +3,7 @@ import { computed } from 'vue';
|
||||
import { NConfigProvider, darkTheme } from 'naive-ui';
|
||||
import { useAppStore } from './store/modules/app';
|
||||
import { useThemeStore } from './store/modules/theme';
|
||||
import { naiveLocales, naiveDateLocales } from './locales/naive';
|
||||
import { naiveDateLocales, naiveLocales } from './locales/naive';
|
||||
|
||||
defineOptions({
|
||||
name: 'App'
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { defineComponent, createTextVNode } from 'vue';
|
||||
import { createTextVNode, defineComponent } from 'vue';
|
||||
import { useDialog, useLoadingBar, useMessage, useNotification } from 'naive-ui';
|
||||
|
||||
defineOptions({
|
||||
@ -17,9 +17,8 @@ const ContextHolder = defineComponent({
|
||||
}
|
||||
|
||||
register();
|
||||
},
|
||||
render() {
|
||||
return createTextVNode();
|
||||
|
||||
return () => createTextVNode();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
defineOptions({ name: 'DarkModeContainer' });
|
||||
|
||||
defineProps<Props>();
|
||||
|
||||
interface Props {
|
||||
inverted?: boolean;
|
||||
}
|
||||
|
||||
defineProps<Props>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@ -4,11 +4,14 @@ import { $t } from '@/locales';
|
||||
|
||||
defineOptions({ name: 'ExceptionBase' });
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
type ExceptionType = '403' | '404' | '500';
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
* exception type
|
||||
* Exception type
|
||||
*
|
||||
* - 403: no permission
|
||||
* - 404: not found
|
||||
* - 500: service error
|
||||
@ -16,8 +19,6 @@ interface Props {
|
||||
type: ExceptionType;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const iconMap: Record<ExceptionType, string> = {
|
||||
'403': 'no-permission',
|
||||
'404': 'not-found',
|
||||
|
||||
@ -5,17 +5,17 @@ defineOptions({
|
||||
name: 'FullScreen'
|
||||
});
|
||||
|
||||
defineProps<Props>();
|
||||
|
||||
interface Props {
|
||||
full?: boolean;
|
||||
}
|
||||
|
||||
defineProps<Props>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ButtonIcon :key="String(full)" :tooltip-content="full ? $t('icon.fullscreenExit') : $t('icon.fullscreen')">
|
||||
<icon-gridicons-fullscreen-exit v-if="full" />
|
||||
<icon-gridicons-fullscreen v-else />
|
||||
<IconGridiconsFullscreenExit v-if="full" />
|
||||
<IconGridiconsFullscreen v-else />
|
||||
</ButtonIcon>
|
||||
</template>
|
||||
|
||||
|
||||
@ -6,31 +6,25 @@ defineOptions({
|
||||
name: 'LangSwitch'
|
||||
});
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
* current language
|
||||
*/
|
||||
lang: App.I18n.LangType;
|
||||
/**
|
||||
* language options
|
||||
*/
|
||||
langOptions: App.I18n.LangOption[];
|
||||
/**
|
||||
* show tooltip
|
||||
*/
|
||||
showTooltip?: boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
showTooltip: true
|
||||
});
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
interface Props {
|
||||
/** Current language */
|
||||
lang: App.I18n.LangType;
|
||||
/** Language options */
|
||||
langOptions: App.I18n.LangOption[];
|
||||
/** Show tooltip */
|
||||
showTooltip?: boolean;
|
||||
}
|
||||
|
||||
type Emits = {
|
||||
(e: 'changeLang', lang: App.I18n.LangType): void;
|
||||
};
|
||||
|
||||
const emits = defineEmits<Emits>();
|
||||
|
||||
const tooltipContent = computed(() => {
|
||||
if (!props.showTooltip) return '';
|
||||
|
||||
@ -38,7 +32,7 @@ const tooltipContent = computed(() => {
|
||||
});
|
||||
|
||||
function changeLang(lang: App.I18n.LangType) {
|
||||
emits('changeLang', lang);
|
||||
emit('changeLang', lang);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@ -1,22 +1,18 @@
|
||||
<script lang="ts" setup>
|
||||
import { $t } from '@/locales';
|
||||
import { computed } from 'vue';
|
||||
import { $t } from '@/locales';
|
||||
|
||||
defineOptions({ name: 'MenuToggler' });
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
* show collapsed icon
|
||||
*/
|
||||
/** Show collapsed icon */
|
||||
collapsed?: boolean;
|
||||
/**
|
||||
* arrow style icon
|
||||
*/
|
||||
/** Arrow style icon */
|
||||
arrowIcon?: boolean;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
type NumberBool = 0 | 1;
|
||||
|
||||
const icon = computed(() => {
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
<script lang="ts" setup>
|
||||
import { $t } from '@/locales';
|
||||
import { computed } from 'vue';
|
||||
import { $t } from '@/locales';
|
||||
|
||||
defineOptions({ name: 'PinToggler' });
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
interface Props {
|
||||
pin?: boolean;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const icon = computed(() => (props.pin ? 'mdi-pin-off' : 'mdi-pin'));
|
||||
</script>
|
||||
|
||||
|
||||
@ -5,16 +5,16 @@ defineOptions({
|
||||
name: 'ReloadButton'
|
||||
});
|
||||
|
||||
defineProps<Props>();
|
||||
|
||||
interface Props {
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
defineProps<Props>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ButtonIcon :tooltip-content="$t('icon.reload')">
|
||||
<icon-ant-design-reload-outlined :class="{ 'animate-spin animate-duration-750': loading }" />
|
||||
<IconAntDesignReloadOutlined :class="{ 'animate-spin animate-duration-750': loading }" />
|
||||
</ButtonIcon>
|
||||
</template>
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ defineOptions({ name: 'SystemLogo' });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<icon-local-logo />
|
||||
<IconLocalLogo />
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
||||
@ -5,32 +5,26 @@ import { $t } from '@/locales';
|
||||
|
||||
defineOptions({ name: 'ThemeSchemaSwitch' });
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
* theme schema
|
||||
*/
|
||||
themeSchema: UnionKey.ThemeScheme;
|
||||
/**
|
||||
* show tooltip
|
||||
*/
|
||||
showTooltip?: boolean;
|
||||
/**
|
||||
* tooltip placement
|
||||
*/
|
||||
tooltipPlacement?: PopoverPlacement;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
showTooltip: true,
|
||||
tooltipPlacement: 'bottom'
|
||||
});
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
interface Props {
|
||||
/** Theme schema */
|
||||
themeSchema: UnionKey.ThemeScheme;
|
||||
/** Show tooltip */
|
||||
showTooltip?: boolean;
|
||||
/** Tooltip placement */
|
||||
tooltipPlacement?: PopoverPlacement;
|
||||
}
|
||||
|
||||
interface Emits {
|
||||
(e: 'switch'): void;
|
||||
}
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
function handleSwitch() {
|
||||
emit('switch');
|
||||
}
|
||||
|
||||
@ -6,16 +6,17 @@ import type { Options } from '@better-scroll/core';
|
||||
|
||||
defineOptions({ name: 'BetterScroll' });
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
* BetterScroll options
|
||||
*
|
||||
* @link https://better-scroll.github.io/docs/zh-CN/guide/base-scroll-options.html
|
||||
*/
|
||||
options: Options;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const bsWrap = ref<HTMLElement>();
|
||||
const bsContent = ref<HTMLElement>();
|
||||
const { width: wrapWidth } = useElementSize(bsWrap);
|
||||
|
||||
@ -8,25 +8,6 @@ defineOptions({
|
||||
inheritAttrs: false
|
||||
});
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
* button class
|
||||
*/
|
||||
class?: string;
|
||||
/**
|
||||
* iconify icon name
|
||||
*/
|
||||
icon?: string;
|
||||
/**
|
||||
* tooltip content
|
||||
*/
|
||||
tooltipContent?: string;
|
||||
/**
|
||||
* tooltip placement
|
||||
*/
|
||||
tooltipPlacement?: PopoverPlacement;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
class: 'h-36px text-icon',
|
||||
icon: '',
|
||||
@ -34,6 +15,17 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
tooltipPlacement: 'bottom'
|
||||
});
|
||||
|
||||
interface Props {
|
||||
/** Button class */
|
||||
class?: string;
|
||||
/** Iconify icon name */
|
||||
icon?: string;
|
||||
/** Tooltip content */
|
||||
tooltipContent?: string;
|
||||
/** Tooltip placement */
|
||||
tooltipPlacement?: PopoverPlacement;
|
||||
}
|
||||
|
||||
interface ButtonProps {
|
||||
className: string;
|
||||
}
|
||||
|
||||
@ -4,24 +4,21 @@ import { Icon } from '@iconify/vue';
|
||||
|
||||
defineOptions({ name: 'SvgIcon' });
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
/**
|
||||
* props
|
||||
* - support iconify and local svg icon
|
||||
* - if icon and localIcon are passed at the same time, localIcon will be rendered first
|
||||
* Props
|
||||
*
|
||||
* - Support iconify and local svg icon
|
||||
* - If icon and localIcon are passed at the same time, localIcon will be rendered first
|
||||
*/
|
||||
interface Props {
|
||||
/**
|
||||
* iconify icon name
|
||||
*/
|
||||
/** Iconify icon name */
|
||||
icon?: string;
|
||||
/**
|
||||
* local svg icon name
|
||||
*/
|
||||
/** Local svg icon name */
|
||||
localIcon?: string;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const attrs = useAttrs();
|
||||
|
||||
const bindAttrs = computed<{ class: string; style: string }>(() => ({
|
||||
@ -39,9 +36,7 @@ const symbolId = computed(() => {
|
||||
return `#${prefix}-${icon}`;
|
||||
});
|
||||
|
||||
/**
|
||||
* if localIcon is passed, render localIcon first
|
||||
*/
|
||||
/** If localIcon is passed, render localIcon first */
|
||||
const renderLocalIcon = computed(() => props.localIcon || !props.icon);
|
||||
</script>
|
||||
|
||||
|
||||
@ -3,9 +3,7 @@ import { computed } from 'vue';
|
||||
import { getColorPalette } from '@sa/utils';
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
* theme color
|
||||
*/
|
||||
/** Theme color */
|
||||
themeColor: string;
|
||||
}
|
||||
|
||||
|
||||
@ -1,34 +1,25 @@
|
||||
export const REG_USER_NAME = /^[\u4e00-\u9fa5a-zA-Z0-9_-]{4,16}$/;
|
||||
export const REG_USER_NAME = /^[\u4E00-\u9FA5a-zA-Z0-9_-]{4,16}$/;
|
||||
|
||||
/**
|
||||
* phone reg
|
||||
*/
|
||||
/** Phone reg */
|
||||
export const REG_PHONE =
|
||||
/^[1](([3][0-9])|([4][01456789])|([5][012356789])|([6][2567])|([7][0-8])|([8][0-9])|([9][012356789]))[0-9]{8}$/;
|
||||
|
||||
/**
|
||||
* password reg
|
||||
* @description 6-18 characters, including letters, numbers, and underscores
|
||||
* Password reg
|
||||
*
|
||||
* 6-18 characters, including letters, numbers, and underscores
|
||||
*/
|
||||
export const REG_PWD = /^\w{6,18}$/;
|
||||
|
||||
/**
|
||||
* email reg
|
||||
*/
|
||||
/** Email reg */
|
||||
export const REG_EMAIL = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
|
||||
|
||||
/**
|
||||
* six digit code reg
|
||||
*/
|
||||
/** Six digit code reg */
|
||||
export const REG_CODE_SIX = /^\d{6}$/;
|
||||
|
||||
/**
|
||||
* four digit code reg
|
||||
*/
|
||||
/** Four digit code reg */
|
||||
export const REG_CODE_FOUR = /^\d{4}$/;
|
||||
|
||||
/**
|
||||
* url reg
|
||||
*/
|
||||
/** Url reg */
|
||||
export const REG_URL =
|
||||
/(((^https?:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)$/;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { ref } from 'vue';
|
||||
import type { FormInst } from 'naive-ui';
|
||||
import { REG_USER_NAME, REG_PHONE, REG_PWD, REG_CODE_SIX, REG_EMAIL } from '@/constants/reg';
|
||||
import { REG_CODE_SIX, REG_EMAIL, REG_PHONE, REG_PWD, REG_USER_NAME } from '@/constants/reg';
|
||||
import { $t } from '@/locales';
|
||||
|
||||
export function useFormRules() {
|
||||
|
||||
@ -4,9 +4,11 @@ import type { RouteKey } from '@elegant-router/types';
|
||||
import { router as globalRouter } from '@/router';
|
||||
|
||||
/**
|
||||
* router push
|
||||
* @description jump to the specified route, it can replace function router.push
|
||||
* @param inSetup whether is in vue script setup
|
||||
* Router push
|
||||
*
|
||||
* Jump to the specified route, it can replace function router.push
|
||||
*
|
||||
* @param inSetup Whether is in vue script setup
|
||||
*/
|
||||
export function useRouterPush(inSetup = true) {
|
||||
const router = inSetup ? useRouter() : globalRouter;
|
||||
@ -44,9 +46,10 @@ export function useRouterPush(inSetup = true) {
|
||||
}
|
||||
|
||||
/**
|
||||
* navigate to login page
|
||||
* @param loginModule the login module
|
||||
* @param redirectUrl the redirect url, if not specified, it will be the current route fullPath
|
||||
* Navigate to login page
|
||||
*
|
||||
* @param loginModule The login module
|
||||
* @param redirectUrl The redirect url, if not specified, it will be the current route fullPath
|
||||
*/
|
||||
async function toLogin(loginModule?: UnionKey.LoginModule, redirectUrl?: string) {
|
||||
const module = loginModule || 'pwd-login';
|
||||
@ -67,7 +70,8 @@ export function useRouterPush(inSetup = true) {
|
||||
}
|
||||
|
||||
/**
|
||||
* toggle login module
|
||||
* Toggle login module
|
||||
*
|
||||
* @param module
|
||||
*/
|
||||
async function toggleLoginModule(module: UnionKey.LoginModule) {
|
||||
@ -76,9 +80,7 @@ export function useRouterPush(inSetup = true) {
|
||||
return routerPushByKey('login', { query, params: { module } });
|
||||
}
|
||||
|
||||
/**
|
||||
* redirect from login
|
||||
*/
|
||||
/** Redirect from login */
|
||||
async function redirectFromLogin() {
|
||||
const redirect = route.value.query?.redirect as string;
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { ref, computed, watch } from 'vue';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useContext } from '@sa/hooks';
|
||||
import { useRouteStore } from '@/store/modules/route';
|
||||
|
||||
@ -7,17 +7,15 @@ defineOptions({
|
||||
name: 'GlobalContent'
|
||||
});
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
* show padding for content
|
||||
*/
|
||||
showPadding?: boolean;
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
showPadding: true
|
||||
});
|
||||
|
||||
interface Props {
|
||||
/** Show padding for content */
|
||||
showPadding?: boolean;
|
||||
}
|
||||
|
||||
const appStore = useAppStore();
|
||||
const themeStore = useThemeStore();
|
||||
const routeStore = useRouteStore();
|
||||
|
||||
@ -7,37 +7,29 @@ import { useRouteStore } from '@/store/modules/route';
|
||||
import HorizontalMenu from '../global-menu/base-menu.vue';
|
||||
import GlobalLogo from '../global-logo/index.vue';
|
||||
import GlobalBreadcrumb from '../global-breadcrumb/index.vue';
|
||||
import { useMixMenuContext } from '../../hooks/use-mix-menu';
|
||||
import ThemeButton from './components/theme-button.vue';
|
||||
import UserAvatar from './components/user-avatar.vue';
|
||||
import { useMixMenuContext } from '../../hooks/use-mix-menu';
|
||||
|
||||
defineOptions({
|
||||
name: 'GlobalHeader'
|
||||
});
|
||||
defineProps<Props>();
|
||||
const appStore = useAppStore();
|
||||
const themeStore = useThemeStore();
|
||||
const routeStore = useRouteStore();
|
||||
const { isFullscreen, toggle } = useFullscreen();
|
||||
const { menus } = useMixMenuContext();
|
||||
|
||||
defineOptions({
|
||||
name: 'GlobalHeader'
|
||||
});
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
* whether to show the logo
|
||||
*/
|
||||
/** Whether to show the logo */
|
||||
showLogo?: App.Global.HeaderProps['showLogo'];
|
||||
/**
|
||||
* whether to show the menu toggler
|
||||
*/
|
||||
/** Whether to show the menu toggler */
|
||||
showMenuToggler?: App.Global.HeaderProps['showMenuToggler'];
|
||||
/**
|
||||
* whether to show the menu
|
||||
*/
|
||||
/** Whether to show the menu */
|
||||
showMenu?: App.Global.HeaderProps['showMenu'];
|
||||
}
|
||||
|
||||
defineProps<Props>();
|
||||
|
||||
const headerMenus = computed(() => {
|
||||
if (themeStore.layout.mode === 'horizontal') {
|
||||
return routeStore.menus;
|
||||
|
||||
@ -5,16 +5,14 @@ defineOptions({
|
||||
name: 'GlobalLogo'
|
||||
});
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
* whether to show the title
|
||||
*/
|
||||
showTitle?: boolean;
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
showTitle: true
|
||||
});
|
||||
|
||||
interface Props {
|
||||
/** Whether to show the title */
|
||||
showTitle?: boolean;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch } from 'vue';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import type { MenuProps, MentionOption } from 'naive-ui';
|
||||
import type { MentionOption, MenuProps } from 'naive-ui';
|
||||
import { SimpleScrollbar } from '@sa/materials';
|
||||
import type { RouteKey } from '@elegant-router/types';
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
@ -13,16 +13,16 @@ defineOptions({
|
||||
name: 'BaseMenu'
|
||||
});
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
mode: 'vertical'
|
||||
});
|
||||
|
||||
interface Props {
|
||||
darkTheme?: boolean;
|
||||
mode?: MenuProps['mode'];
|
||||
menus: App.Global.Menu[];
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
mode: 'vertical'
|
||||
});
|
||||
|
||||
const route = useRoute();
|
||||
const appStore = useAppStore();
|
||||
const themeStore = useThemeStore();
|
||||
|
||||
@ -11,39 +11,31 @@ defineOptions({
|
||||
name: 'FirstLevelMenu'
|
||||
});
|
||||
|
||||
defineProps<Props>();
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
interface Props {
|
||||
activeMenuKey?: string;
|
||||
inverted?: boolean;
|
||||
}
|
||||
|
||||
defineProps<Props>();
|
||||
|
||||
interface Emits {
|
||||
(e: 'select', menu: App.Global.Menu): boolean;
|
||||
}
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const appStore = useAppStore();
|
||||
const themeStore = useThemeStore();
|
||||
const routeStore = useRouteStore();
|
||||
|
||||
interface MixMenuItemProps {
|
||||
/**
|
||||
* menu item label
|
||||
*/
|
||||
/** Menu item label */
|
||||
label: App.Global.Menu['label'];
|
||||
/**
|
||||
* menu item icon
|
||||
*/
|
||||
/** Menu item icon */
|
||||
icon: App.Global.Menu['icon'];
|
||||
/**
|
||||
* active menu item
|
||||
*/
|
||||
/** Active menu item */
|
||||
active: boolean;
|
||||
/**
|
||||
* mini size
|
||||
*/
|
||||
/** Mini size */
|
||||
isMini: boolean;
|
||||
}
|
||||
const [DefineMixMenuItem, MixMenuItem] = createReusableTemplate<MixMenuItemProps>();
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import FirstLevelMenu from './first-level-menu.vue';
|
||||
import { useMixMenuContext } from '../../hooks/use-mix-menu';
|
||||
import { useRouterPush } from '@/hooks/common/router';
|
||||
import { useMixMenuContext } from '../../hooks/use-mix-menu';
|
||||
import FirstLevelMenu from './first-level-menu.vue';
|
||||
|
||||
defineOptions({
|
||||
name: 'HorizontalMixMenu'
|
||||
|
||||
@ -5,9 +5,9 @@ import { useAppStore } from '@/store/modules/app';
|
||||
import { useRouteStore } from '@/store/modules/route';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { useRouterPush } from '@/hooks/common/router';
|
||||
import { useMixMenu } from '../../hooks/use-mix-menu';
|
||||
import FirstLevelMenu from './first-level-menu.vue';
|
||||
import BaseMenu from './base-menu.vue';
|
||||
import { useMixMenu } from '../../hooks/use-mix-menu';
|
||||
|
||||
defineOptions({
|
||||
name: 'VerticalMixMenu'
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import type { VNode } from 'vue';
|
||||
import { $t } from '@/locales';
|
||||
import { useSvgIconRender } from '@sa/hooks';
|
||||
import { $t } from '@/locales';
|
||||
import { useTabStore } from '@/store/modules/tab';
|
||||
import SvgIcon from '@/components/custom/svg-icon.vue';
|
||||
|
||||
@ -10,25 +10,21 @@ defineOptions({
|
||||
name: 'ContextMenu'
|
||||
});
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
excludeKeys: () => [],
|
||||
disabledKeys: () => []
|
||||
});
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
* clientX
|
||||
*/
|
||||
/** ClientX */
|
||||
x: number;
|
||||
/**
|
||||
* clientY
|
||||
*/
|
||||
/** ClientY */
|
||||
y: number;
|
||||
tabId: string;
|
||||
excludeKeys?: App.Global.DropdownKey[];
|
||||
disabledKeys?: App.Global.DropdownKey[];
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
excludeKeys: () => [],
|
||||
disabledKeys: () => []
|
||||
});
|
||||
|
||||
const visible = defineModel<boolean>('visible');
|
||||
|
||||
const { removeTab, clearTabs, clearLeftTabs, clearRightTabs } = useTabStore();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, watch, nextTick } from 'vue';
|
||||
import { nextTick, reactive, ref, watch } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useElementBounding } from '@vueuse/core';
|
||||
import { PageTab } from '@sa/materials';
|
||||
|
||||
@ -7,28 +7,22 @@ defineOptions({
|
||||
name: 'LayoutModeCard'
|
||||
});
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
* layout mode
|
||||
*/
|
||||
/** Layout mode */
|
||||
mode: UnionKey.ThemeLayoutMode;
|
||||
/**
|
||||
* disabled
|
||||
*/
|
||||
/** Disabled */
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
interface Emits {
|
||||
/**
|
||||
* layout mode change
|
||||
*/
|
||||
/** Layout mode change */
|
||||
(e: 'update:mode', mode: UnionKey.ThemeLayoutMode): void;
|
||||
}
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
type LayoutConfig = Record<
|
||||
UnionKey.ThemeLayoutMode,
|
||||
{
|
||||
|
||||
@ -3,14 +3,12 @@ defineOptions({
|
||||
name: 'SettingItem'
|
||||
});
|
||||
|
||||
defineProps<Props>();
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
* label
|
||||
*/
|
||||
/** Label */
|
||||
label: string;
|
||||
}
|
||||
|
||||
defineProps<Props>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import Clipboard from 'clipboard';
|
||||
import { $t } from '@/locales';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
import { computed } from 'vue';
|
||||
import { $t } from '@/locales';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { themeScrollModeOptions, themePageAnimationModeOptions, themeTabModeOptions } from '@/constants/app';
|
||||
import { themePageAnimationModeOptions, themeScrollModeOptions, themeTabModeOptions } from '@/constants/app';
|
||||
import SettingItem from '../components/setting-item.vue';
|
||||
|
||||
defineOptions({
|
||||
|
||||
@ -4,7 +4,8 @@ import 'dayjs/locale/en';
|
||||
import { localStg } from '@/utils/storage';
|
||||
|
||||
/**
|
||||
* set dayjs locale
|
||||
* Set dayjs locale
|
||||
*
|
||||
* @param lang
|
||||
*/
|
||||
export function setDayjsLocale(lang: App.I18n.LangType = 'zh-CN') {
|
||||
|
||||
@ -11,7 +11,8 @@ const i18n = createI18n({
|
||||
});
|
||||
|
||||
/**
|
||||
* setup plugin i18n
|
||||
* Setup plugin i18n
|
||||
*
|
||||
* @param app
|
||||
*/
|
||||
export function setupI18n(app: App) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { zhCN, enUS, dateZhCN, dateEnUS } from 'naive-ui';
|
||||
import type { NLocale, NDateLocale } from 'naive-ui';
|
||||
import { dateEnUS, dateZhCN, enUS, zhCN } from 'naive-ui';
|
||||
import type { NDateLocale, NLocale } from 'naive-ui';
|
||||
|
||||
export const naiveLocales: Record<App.I18n.LangType, NLocale> = {
|
||||
'zh-CN': zhCN,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { createApp } from 'vue';
|
||||
import './plugins/assets';
|
||||
import { setupNProgress, setupIconifyOffline, setupDayjs } from './plugins';
|
||||
import { setupDayjs, setupIconifyOffline, setupNProgress } from './plugins';
|
||||
import { setupStore } from './store';
|
||||
import { setupRouter } from './router';
|
||||
import { setupI18n } from './locales';
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import { addAPIProvider, disableCache } from '@iconify/vue';
|
||||
|
||||
/**
|
||||
* setup the iconify offline
|
||||
*/
|
||||
/** Setup the iconify offline */
|
||||
export function setupIconifyOffline() {
|
||||
const { VITE_ICONIFY_URL } = import.meta.env;
|
||||
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import NProgress from 'nprogress';
|
||||
|
||||
/**
|
||||
* setup plugin NProgress
|
||||
*/
|
||||
/** Setup plugin NProgress */
|
||||
export function setupNProgress() {
|
||||
NProgress.configure({ easing: 'ease', speed: 500 });
|
||||
|
||||
|
||||
@ -4,8 +4,9 @@ import { createDocumentTitleGuard } from './title';
|
||||
import { createPermissionGuard } from './permission';
|
||||
|
||||
/**
|
||||
* router guard
|
||||
* @param router - router instance
|
||||
* Router guard
|
||||
*
|
||||
* @param router - Router instance
|
||||
*/
|
||||
export function createRouterGuard(router: Router) {
|
||||
createProgressGuard(router);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { Router, NavigationGuardNext, RouteLocationNormalized } from 'vue-router';
|
||||
import type { NavigationGuardNext, RouteLocationNormalized, Router } from 'vue-router';
|
||||
import type { RouteKey, RoutePath } from '@elegant-router/types';
|
||||
import { useAuthStore } from '@/store/modules/auth';
|
||||
import { useRouteStore } from '@/store/modules/route';
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { $t } from '@/locales';
|
||||
import { useTitle } from '@vueuse/core';
|
||||
import type { Router } from 'vue-router';
|
||||
import { $t } from '@/locales';
|
||||
|
||||
export function createDocumentTitleGuard(router: Router) {
|
||||
router.afterEach(to => {
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import type { App } from 'vue';
|
||||
import {
|
||||
createRouter,
|
||||
createWebHistory,
|
||||
createWebHashHistory,
|
||||
type RouterHistory,
|
||||
createMemoryHistory,
|
||||
type RouterHistory
|
||||
createRouter,
|
||||
createWebHashHistory,
|
||||
createWebHistory
|
||||
} from 'vue-router';
|
||||
import { createRoutes } from './routes';
|
||||
import { createRouterGuard } from './guard';
|
||||
@ -24,9 +24,7 @@ export const router = createRouter({
|
||||
routes: constantVueRoutes
|
||||
});
|
||||
|
||||
/**
|
||||
* setup Vue Router
|
||||
*/
|
||||
/** Setup Vue Router */
|
||||
export async function setupRouter(app: App) {
|
||||
app.use(router);
|
||||
createRouterGuard(router);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { ElegantConstRoute, ElegantRoute, CustomRoute } from '@elegant-router/types';
|
||||
import type { CustomRoute, ElegantConstRoute, ElegantRoute } from '@elegant-router/types';
|
||||
import { generatedRoutes } from '../elegant/routes';
|
||||
import { layouts, views } from '../elegant/imports';
|
||||
import { transformElegantRoutesToVueRoutes } from '../elegant/transform';
|
||||
@ -26,9 +26,7 @@ const customRoutes: CustomRoute[] = [
|
||||
}
|
||||
];
|
||||
|
||||
/**
|
||||
* create routes
|
||||
*/
|
||||
/** Create routes */
|
||||
export function createRoutes() {
|
||||
const constantRoutes: ElegantRoute[] = [];
|
||||
|
||||
@ -51,8 +49,9 @@ export function createRoutes() {
|
||||
}
|
||||
|
||||
/**
|
||||
* get auth vue routes
|
||||
* @param routes elegant routes
|
||||
* Get auth vue routes
|
||||
*
|
||||
* @param routes Elegant routes
|
||||
*/
|
||||
export function getAuthVueRoutes(routes: ElegantConstRoute[]) {
|
||||
return transformElegantRoutesToVueRoutes(routes, layouts, views);
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { request } from '../request';
|
||||
|
||||
/**
|
||||
* login
|
||||
* @param userName user name
|
||||
* @param password password
|
||||
* Login
|
||||
*
|
||||
* @param userName User name
|
||||
* @param password Password
|
||||
*/
|
||||
export function fetchLogin(userName: string, password: string) {
|
||||
return request<App.Service.Response<Api.Auth.LoginToken>>('/auth/login', {
|
||||
@ -15,16 +16,15 @@ export function fetchLogin(userName: string, password: string) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* get user info
|
||||
*/
|
||||
/** Get user info */
|
||||
export function fetchGetUserInfo() {
|
||||
return request<App.Service.Response<Api.Auth.UserInfo>>('/auth/getUserInfo');
|
||||
}
|
||||
|
||||
/**
|
||||
* refresh token
|
||||
* @param refreshToken refresh token
|
||||
* Refresh token
|
||||
*
|
||||
* @param refreshToken Refresh token
|
||||
*/
|
||||
export function fetchRefreshToken(refreshToken: string) {
|
||||
return request<App.Service.Response<Api.Auth.LoginToken>>('/auth/refreshToken', {
|
||||
|
||||
@ -1,17 +1,19 @@
|
||||
import { request } from '../request';
|
||||
|
||||
/**
|
||||
* get user routes
|
||||
* @param example whether to use example data, default: 0
|
||||
* Get user routes
|
||||
*
|
||||
* @param example Whether to use example data, default: 0
|
||||
*/
|
||||
export function fetchGetUserRoutes(example: '0' | '1' = '0') {
|
||||
return request<App.Service.Response<Api.Route.UserRoute>>('/route/getUserRoutes', { params: { example } });
|
||||
}
|
||||
|
||||
/**
|
||||
* whether the route is exist
|
||||
* @param routeName route name
|
||||
* @param example whether to use example data, default: 0
|
||||
* Whether the route is exist
|
||||
*
|
||||
* @param routeName Route name
|
||||
* @param example Whether to use example data, default: 0
|
||||
*/
|
||||
export function fetchIsRouteExist(routeName: string, example: '0' | '1' = '0') {
|
||||
return request<App.Service.Response<boolean>>('/route/isRouteExist', { params: { routeName, example } });
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { localStg } from '@/utils/storage';
|
||||
import { createOfetch as createRequest } from '@sa/request';
|
||||
import { createServiceConfig, createProxyPattern } from '~/env.config';
|
||||
import { localStg } from '@/utils/storage';
|
||||
import { createProxyPattern, createServiceConfig } from '~/env.config';
|
||||
|
||||
const { baseURL, otherBaseURL } = createServiceConfig(import.meta.env);
|
||||
|
||||
|
||||
@ -2,9 +2,7 @@ import type { App } from 'vue';
|
||||
import { createPinia } from 'pinia';
|
||||
import { resetSetupStore } from './plugins';
|
||||
|
||||
/**
|
||||
* setup Vue store plugin pinia
|
||||
*/
|
||||
/** Setup Vue store plugin pinia */
|
||||
export function setupStore(app: App) {
|
||||
const store = createPinia();
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { ref, watch, effectScope, onScopeDispose } from 'vue';
|
||||
import { effectScope, onScopeDispose, ref, watch } from 'vue';
|
||||
import { defineStore } from 'pinia';
|
||||
import { breakpointsTailwind, useBreakpoints, useTitle } from '@vueuse/core';
|
||||
import { useBoolean } from '@sa/hooks';
|
||||
@ -24,14 +24,13 @@ export const useAppStore = defineStore(SetupStoreId.App, () => {
|
||||
const { bool: siderCollapse, setBool: setSiderCollapse, toggle: toggleSiderCollapse } = useBoolean();
|
||||
const { bool: mixSiderFixed, setBool: setMixSiderFixed, toggle: toggleMixSiderFixed } = useBoolean();
|
||||
|
||||
/**
|
||||
* is mobile layout
|
||||
*/
|
||||
/** Is mobile layout */
|
||||
const isMobile = breakpoints.smaller('sm');
|
||||
|
||||
/**
|
||||
* reload page
|
||||
* @param duration duration time
|
||||
* Reload page
|
||||
*
|
||||
* @param duration Duration time
|
||||
*/
|
||||
async function reloadPage(duration = 0) {
|
||||
setReloadFlag(false);
|
||||
@ -64,9 +63,7 @@ export const useAppStore = defineStore(SetupStoreId.App, () => {
|
||||
localStg.set('lang', lang);
|
||||
}
|
||||
|
||||
/**
|
||||
* update document title by locale
|
||||
*/
|
||||
/** Update document title by locale */
|
||||
function updateDocumentTitleByLocale() {
|
||||
const { i18nKey, title } = router.currentRoute.value.meta;
|
||||
|
||||
@ -110,9 +107,7 @@ export const useAppStore = defineStore(SetupStoreId.App, () => {
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* on scope dispose
|
||||
*/
|
||||
/** On scope dispose */
|
||||
onScopeDispose(() => {
|
||||
scope.stop();
|
||||
});
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { ref, reactive, computed } from 'vue';
|
||||
import { computed, reactive, ref } from 'vue';
|
||||
import { defineStore } from 'pinia';
|
||||
import { useLoading } from '@sa/hooks';
|
||||
import { SetupStoreId } from '@/enum';
|
||||
import { useRouterPush } from '@/hooks/common/router';
|
||||
import { fetchLogin, fetchGetUserInfo } from '@/service/api';
|
||||
import { fetchGetUserInfo, fetchLogin } from '@/service/api';
|
||||
import { localStg } from '@/utils/storage';
|
||||
import { useRouteStore } from '../route';
|
||||
import { getToken, getUserInfo, clearAuthStorage } from './shared';
|
||||
import { $t } from '@/locales';
|
||||
import { useRouteStore } from '../route';
|
||||
import { clearAuthStorage, getToken, getUserInfo } from './shared';
|
||||
|
||||
export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
||||
const routeStore = useRouteStore();
|
||||
@ -18,14 +18,10 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
||||
|
||||
const userInfo: Api.Auth.UserInfo = reactive(getUserInfo());
|
||||
|
||||
/**
|
||||
* is login
|
||||
*/
|
||||
/** Is login */
|
||||
const isLogin = computed(() => Boolean(token.value));
|
||||
|
||||
/**
|
||||
* reset auth store
|
||||
*/
|
||||
/** Reset auth store */
|
||||
async function resetStore() {
|
||||
const authStore = useAuthStore();
|
||||
|
||||
@ -41,9 +37,10 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* login
|
||||
* @param userName user name
|
||||
* @param password password
|
||||
* Login
|
||||
*
|
||||
* @param userName User name
|
||||
* @param password Password
|
||||
*/
|
||||
async function login(userName: string, password: string) {
|
||||
startLoading();
|
||||
|
||||
@ -1,15 +1,11 @@
|
||||
import { localStg } from '@/utils/storage';
|
||||
|
||||
/**
|
||||
* get token
|
||||
*/
|
||||
/** Get token */
|
||||
export function getToken() {
|
||||
return localStg.get('token') || '';
|
||||
}
|
||||
|
||||
/**
|
||||
* get user info
|
||||
*/
|
||||
/** Get user info */
|
||||
export function getUserInfo() {
|
||||
const emptyInfo: Api.Auth.UserInfo = {
|
||||
userId: '',
|
||||
@ -21,9 +17,7 @@ export function getUserInfo() {
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* clear auth storage
|
||||
*/
|
||||
/** Clear auth storage */
|
||||
export function clearAuthStorage() {
|
||||
localStg.remove('token');
|
||||
localStg.remove('refreshToken');
|
||||
|
||||
@ -1,25 +1,25 @@
|
||||
import { ref, computed } from 'vue';
|
||||
import { computed, ref } from 'vue';
|
||||
import type { RouteRecordRaw } from 'vue-router';
|
||||
import { defineStore } from 'pinia';
|
||||
import { useBoolean } from '@sa/hooks';
|
||||
import type { ElegantConstRoute, CustomRoute, RouteKey, LastLevelRouteKey, RouteMap } from '@elegant-router/types';
|
||||
import type { CustomRoute, ElegantConstRoute, LastLevelRouteKey, RouteKey, RouteMap } from '@elegant-router/types';
|
||||
import { SetupStoreId } from '@/enum';
|
||||
import { router } from '@/router';
|
||||
import { createRoutes, getAuthVueRoutes, ROOT_ROUTE } from '@/router/routes';
|
||||
import { getRoutePath, getRouteName } from '@/router/elegant/transform';
|
||||
import { ROOT_ROUTE, createRoutes, getAuthVueRoutes } from '@/router/routes';
|
||||
import { getRouteName, getRoutePath } from '@/router/elegant/transform';
|
||||
import { fetchGetUserRoutes, fetchIsRouteExist } from '@/service/api';
|
||||
import {
|
||||
filterAuthRoutesByRoles,
|
||||
getGlobalMenusByAuthRoutes,
|
||||
updateLocaleOfGlobalMenus,
|
||||
getCacheRouteNames,
|
||||
isRouteExistByRouteName,
|
||||
getSelectedMenuKeyPathByKey,
|
||||
getBreadcrumbsByRoute
|
||||
} from './shared';
|
||||
import { useAppStore } from '../app';
|
||||
import { useAuthStore } from '../auth';
|
||||
import { useTabStore } from '../tab';
|
||||
import {
|
||||
filterAuthRoutesByRoles,
|
||||
getBreadcrumbsByRoute,
|
||||
getCacheRouteNames,
|
||||
getGlobalMenusByAuthRoutes,
|
||||
getSelectedMenuKeyPathByKey,
|
||||
isRouteExistByRouteName,
|
||||
updateLocaleOfGlobalMenus
|
||||
} from './shared';
|
||||
|
||||
export const useRouteStore = defineStore(SetupStoreId.Route, () => {
|
||||
const appStore = useAppStore();
|
||||
@ -29,52 +29,46 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
|
||||
const removeRouteFns: (() => void)[] = [];
|
||||
|
||||
/**
|
||||
* auth route mode
|
||||
* @description it recommends to use static mode in the development environment, and use dynamic mode in the production environment,
|
||||
* if use static mode in development environment, the auth routes will be auto generated by plugin "@elegant-router/vue"
|
||||
* Auth route mode
|
||||
*
|
||||
* It recommends to use static mode in the development environment, and use dynamic mode in the production
|
||||
* environment, if use static mode in development environment, the auth routes will be auto generated by plugin
|
||||
* "@elegant-router/vue"
|
||||
*/
|
||||
const authRouteMode = ref(import.meta.env.VITE_AUTH_ROUTE_MODE);
|
||||
|
||||
/**
|
||||
* home route key
|
||||
*/
|
||||
/** Home route key */
|
||||
const routeHome = ref(import.meta.env.VITE_ROUTE_HOME);
|
||||
|
||||
/**
|
||||
* set route home
|
||||
* @param routeKey route key
|
||||
* Set route home
|
||||
*
|
||||
* @param routeKey Route key
|
||||
*/
|
||||
function setRouteHome(routeKey: LastLevelRouteKey) {
|
||||
routeHome.value = routeKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* global menus
|
||||
*/
|
||||
/** Global menus */
|
||||
const menus = ref<App.Global.Menu[]>([]);
|
||||
|
||||
/**
|
||||
* get global menus
|
||||
*/
|
||||
/** Get global menus */
|
||||
function getGlobalMenus(routes: ElegantConstRoute[]) {
|
||||
menus.value = getGlobalMenusByAuthRoutes(routes);
|
||||
}
|
||||
|
||||
/**
|
||||
* update global menus by locale
|
||||
*/
|
||||
/** Update global menus by locale */
|
||||
function updateGlobalMenusByLocale() {
|
||||
menus.value = updateLocaleOfGlobalMenus(menus.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* cache routes
|
||||
*/
|
||||
/** Cache routes */
|
||||
const cacheRoutes = ref<RouteKey[]>([]);
|
||||
|
||||
/**
|
||||
* get cache routes
|
||||
* @param routes vue routes
|
||||
* Get cache routes
|
||||
*
|
||||
* @param routes Vue routes
|
||||
*/
|
||||
function getCacheRoutes(routes: RouteRecordRaw[]) {
|
||||
const { constantVueRoutes } = createRoutes();
|
||||
@ -83,7 +77,8 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* add cache routes
|
||||
* Add cache routes
|
||||
*
|
||||
* @param routeKey
|
||||
*/
|
||||
function addCacheRoutes(routeKey: RouteKey) {
|
||||
@ -93,7 +88,8 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* remove cache routes
|
||||
* Remove cache routes
|
||||
*
|
||||
* @param routeKey
|
||||
*/
|
||||
function removeCacheRoutes(routeKey: RouteKey) {
|
||||
@ -105,7 +101,8 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* re-cache routes by route key
|
||||
* Re-cache routes by route key
|
||||
*
|
||||
* @param routeKey
|
||||
*/
|
||||
async function reCacheRoutesByKey(routeKey: RouteKey) {
|
||||
@ -117,7 +114,8 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* re-cache routes by route keys
|
||||
* Re-cache routes by route keys
|
||||
*
|
||||
* @param routeKeys
|
||||
*/
|
||||
async function reCacheRoutesByKeys(routeKeys: RouteKey[]) {
|
||||
@ -126,14 +124,10 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* global breadcrumbs
|
||||
*/
|
||||
/** Global breadcrumbs */
|
||||
const breadcrumbs = computed(() => getBreadcrumbsByRoute(router.currentRoute.value, menus.value));
|
||||
|
||||
/**
|
||||
* reset store
|
||||
*/
|
||||
/** Reset store */
|
||||
async function resetStore() {
|
||||
const routeStore = useRouteStore();
|
||||
|
||||
@ -142,17 +136,13 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
|
||||
resetVueRoutes();
|
||||
}
|
||||
|
||||
/**
|
||||
* reset vue routes
|
||||
*/
|
||||
/** Reset vue routes */
|
||||
function resetVueRoutes() {
|
||||
removeRouteFns.forEach(fn => fn());
|
||||
removeRouteFns.length = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* init auth route
|
||||
*/
|
||||
/** Init auth route */
|
||||
async function initAuthRoute() {
|
||||
if (authRouteMode.value === 'static') {
|
||||
await initStaticAuthRoute();
|
||||
@ -163,9 +153,7 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
|
||||
tabStore.initHomeTab(router);
|
||||
}
|
||||
|
||||
/**
|
||||
* init static auth route
|
||||
*/
|
||||
/** Init static auth route */
|
||||
async function initStaticAuthRoute() {
|
||||
const { authRoutes } = createRoutes();
|
||||
|
||||
@ -176,9 +164,7 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
|
||||
setIsInitAuthRoute(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* init dynamic auth route
|
||||
*/
|
||||
/** Init dynamic auth route */
|
||||
async function initDynamicAuthRoute() {
|
||||
const {
|
||||
data: { routes, home }
|
||||
@ -194,8 +180,9 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* handle routes
|
||||
* @param routes auth routes
|
||||
* Handle routes
|
||||
*
|
||||
* @param routes Auth routes
|
||||
*/
|
||||
function handleAuthRoutes(routes: ElegantConstRoute[]) {
|
||||
const vueRoutes = getAuthVueRoutes(routes);
|
||||
@ -208,8 +195,9 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* add routes to vue router
|
||||
* @param routes vue routes
|
||||
* Add routes to vue router
|
||||
*
|
||||
* @param routes Vue routes
|
||||
*/
|
||||
function addRoutesToVueRouter(routes: RouteRecordRaw[]) {
|
||||
routes.forEach(route => {
|
||||
@ -219,7 +207,8 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* add remove route fn
|
||||
* Add remove route fn
|
||||
*
|
||||
* @param fn
|
||||
*/
|
||||
function addRemoveRouteFn(fn: () => void) {
|
||||
@ -227,8 +216,9 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* update root route redirect when auth route mode is dynamic
|
||||
* @param redirectKey redirect route key
|
||||
* Update root route redirect when auth route mode is dynamic
|
||||
*
|
||||
* @param redirectKey Redirect route key
|
||||
*/
|
||||
function handleUpdateRootRouteRedirect(redirectKey: LastLevelRouteKey) {
|
||||
const redirect = getRoutePath(redirectKey);
|
||||
@ -245,8 +235,9 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* get is auth route exist
|
||||
* @param routePath route path
|
||||
* Get is auth route exist
|
||||
*
|
||||
* @param routePath Route path
|
||||
*/
|
||||
async function getIsAuthRouteExist(routePath: RouteMap[RouteKey]) {
|
||||
const routeName = getRouteName(routePath);
|
||||
@ -267,8 +258,9 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* get selected menu key path
|
||||
* @param selectedKey selected menu key
|
||||
* Get selected menu key path
|
||||
*
|
||||
* @param selectedKey Selected menu key
|
||||
*/
|
||||
function getSelectedMenuKeyPath(selectedKey: string) {
|
||||
return getSelectedMenuKeyPathByKey(selectedKey, menus.value);
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
import type { RouteRecordRaw, _RouteRecordBase, RouteLocationNormalizedLoaded } from 'vue-router';
|
||||
import type { ElegantConstRoute, RouteKey, RouteMap, LastLevelRouteKey } from '@elegant-router/types';
|
||||
import type { RouteLocationNormalizedLoaded, RouteRecordRaw, _RouteRecordBase } from 'vue-router';
|
||||
import type { ElegantConstRoute, LastLevelRouteKey, RouteKey, RouteMap } from '@elegant-router/types';
|
||||
import { useSvgIconRender } from '@sa/hooks';
|
||||
import { $t } from '@/locales';
|
||||
import SvgIcon from '@/components/custom/svg-icon.vue';
|
||||
|
||||
/**
|
||||
* filter auth routes by roles
|
||||
* @param routes auth routes
|
||||
* @param roles roles
|
||||
* Filter auth routes by roles
|
||||
*
|
||||
* @param routes Auth routes
|
||||
* @param roles Roles
|
||||
*/
|
||||
export function filterAuthRoutesByRoles(routes: ElegantConstRoute[], roles: string[]) {
|
||||
const SUPER_ROLE = 'R_SUPER';
|
||||
@ -20,9 +21,10 @@ export function filterAuthRoutesByRoles(routes: ElegantConstRoute[], roles: stri
|
||||
}
|
||||
|
||||
/**
|
||||
* filter auth route by roles
|
||||
* @param route auth route
|
||||
* @param roles roles
|
||||
* Filter auth route by roles
|
||||
*
|
||||
* @param route Auth route
|
||||
* @param roles Roles
|
||||
*/
|
||||
function filterAuthRouteByRoles(route: ElegantConstRoute, roles: string[]) {
|
||||
const routeRoles = (route.meta && route.meta.roles) || [];
|
||||
@ -43,8 +45,9 @@ function filterAuthRouteByRoles(route: ElegantConstRoute, roles: string[]) {
|
||||
}
|
||||
|
||||
/**
|
||||
* get global menus by auth routes
|
||||
* @param routes auth routes
|
||||
* Get global menus by auth routes
|
||||
*
|
||||
* @param routes Auth routes
|
||||
*/
|
||||
export function getGlobalMenusByAuthRoutes(routes: ElegantConstRoute[]) {
|
||||
const menus: App.Global.Menu[] = [];
|
||||
@ -65,7 +68,8 @@ export function getGlobalMenusByAuthRoutes(routes: ElegantConstRoute[]) {
|
||||
}
|
||||
|
||||
/**
|
||||
* update locale of global menus
|
||||
* Update locale of global menus
|
||||
*
|
||||
* @param menus
|
||||
*/
|
||||
export function updateLocaleOfGlobalMenus(menus: App.Global.Menu[]) {
|
||||
@ -92,7 +96,8 @@ export function updateLocaleOfGlobalMenus(menus: App.Global.Menu[]) {
|
||||
}
|
||||
|
||||
/**
|
||||
* get global menu by route
|
||||
* Get global menu by route
|
||||
*
|
||||
* @param route
|
||||
*/
|
||||
function getGlobalMenuByBaseRoute(route: RouteLocationNormalizedLoaded | ElegantConstRoute) {
|
||||
@ -116,8 +121,9 @@ function getGlobalMenuByBaseRoute(route: RouteLocationNormalizedLoaded | Elegant
|
||||
}
|
||||
|
||||
/**
|
||||
* get cache route names
|
||||
* @param routes vue routes (two levels)
|
||||
* Get cache route names
|
||||
*
|
||||
* @param routes Vue routes (two levels)
|
||||
*/
|
||||
export function getCacheRouteNames(routes: RouteRecordRaw[]) {
|
||||
const cacheNames: LastLevelRouteKey[] = [];
|
||||
@ -135,7 +141,8 @@ export function getCacheRouteNames(routes: RouteRecordRaw[]) {
|
||||
}
|
||||
|
||||
/**
|
||||
* is route exist by route name
|
||||
* Is route exist by route name
|
||||
*
|
||||
* @param routeName
|
||||
* @param routes
|
||||
*/
|
||||
@ -144,7 +151,8 @@ export function isRouteExistByRouteName(routeName: RouteKey, routes: ElegantCons
|
||||
}
|
||||
|
||||
/**
|
||||
* recursive get is route exist by route name
|
||||
* Recursive get is route exist by route name
|
||||
*
|
||||
* @param route
|
||||
* @param routeName
|
||||
*/
|
||||
@ -163,7 +171,8 @@ function recursiveGetIsRouteExistByRouteName(route: ElegantConstRoute, routeName
|
||||
}
|
||||
|
||||
/**
|
||||
* get selected menu key path
|
||||
* Get selected menu key path
|
||||
*
|
||||
* @param selectedKey
|
||||
* @param menus
|
||||
*/
|
||||
@ -186,9 +195,10 @@ export function getSelectedMenuKeyPathByKey(selectedKey: string, menus: App.Glob
|
||||
}
|
||||
|
||||
/**
|
||||
* find menu path
|
||||
* @param targetKey target menu key
|
||||
* @param menu menu
|
||||
* Find menu path
|
||||
*
|
||||
* @param targetKey Target menu key
|
||||
* @param menu Menu
|
||||
*/
|
||||
function findMenuPath(targetKey: string, menu: App.Global.Menu): string[] | null {
|
||||
const path: string[] = [];
|
||||
@ -221,7 +231,8 @@ function findMenuPath(targetKey: string, menu: App.Global.Menu): string[] | null
|
||||
}
|
||||
|
||||
/**
|
||||
* transform menu to breadcrumb
|
||||
* Transform menu to breadcrumb
|
||||
*
|
||||
* @param menu
|
||||
*/
|
||||
function transformMenuToBreadcrumb(menu: App.Global.Menu) {
|
||||
@ -239,7 +250,8 @@ function transformMenuToBreadcrumb(menu: App.Global.Menu) {
|
||||
}
|
||||
|
||||
/**
|
||||
* get breadcrumbs by route
|
||||
* Get breadcrumbs by route
|
||||
*
|
||||
* @param route
|
||||
* @param menus
|
||||
*/
|
||||
|
||||
@ -3,64 +3,59 @@ import type { Router } from 'vue-router';
|
||||
import { defineStore } from 'pinia';
|
||||
import { useEventListener } from '@vueuse/core';
|
||||
import { SetupStoreId } from '@/enum';
|
||||
import {
|
||||
getAllTabs,
|
||||
getDefaultHomeTab,
|
||||
getTabByRoute,
|
||||
isTabInTabs,
|
||||
filterTabsById,
|
||||
getFixedTabIds,
|
||||
filterTabsByIds,
|
||||
updateTabsByI18nKey,
|
||||
updateTabByI18nKey
|
||||
} from './shared';
|
||||
import { useRouterPush } from '@/hooks/common/router';
|
||||
import { localStg } from '@/utils/storage';
|
||||
import { useThemeStore } from '../theme';
|
||||
import {
|
||||
filterTabsById,
|
||||
filterTabsByIds,
|
||||
getAllTabs,
|
||||
getDefaultHomeTab,
|
||||
getFixedTabIds,
|
||||
getTabByRoute,
|
||||
isTabInTabs,
|
||||
updateTabByI18nKey,
|
||||
updateTabsByI18nKey
|
||||
} from './shared';
|
||||
|
||||
export const useTabStore = defineStore(SetupStoreId.Tab, () => {
|
||||
const themeStore = useThemeStore();
|
||||
const { routerPush } = useRouterPush(false);
|
||||
|
||||
/**
|
||||
* tabs
|
||||
*/
|
||||
/** Tabs */
|
||||
const tabs = ref<App.Global.Tab[]>([]);
|
||||
|
||||
/**
|
||||
* get active tab
|
||||
*/
|
||||
/** Get active tab */
|
||||
const homeTab = ref<App.Global.Tab>();
|
||||
|
||||
/**
|
||||
* init home tab
|
||||
* @param router router instance
|
||||
* Init home tab
|
||||
*
|
||||
* @param router Router instance
|
||||
*/
|
||||
function initHomeTab(router: Router) {
|
||||
homeTab.value = getDefaultHomeTab(router);
|
||||
}
|
||||
|
||||
/**
|
||||
* get all tabs
|
||||
*/
|
||||
/** Get all tabs */
|
||||
const allTabs = computed(() => getAllTabs(tabs.value, homeTab.value));
|
||||
|
||||
/**
|
||||
* active tab id
|
||||
*/
|
||||
/** Active tab id */
|
||||
const activeTabId = ref<string>('');
|
||||
|
||||
/**
|
||||
* set active tab id
|
||||
* @param id tab id
|
||||
* Set active tab id
|
||||
*
|
||||
* @param id Tab id
|
||||
*/
|
||||
function setActiveTabId(id: string) {
|
||||
activeTabId.value = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* init tab store
|
||||
* @param currentRoute current route
|
||||
* Init tab store
|
||||
*
|
||||
* @param currentRoute Current route
|
||||
*/
|
||||
function initTabStore(currentRoute: App.Global.TabRoute) {
|
||||
const storageTabs = localStg.get('globalTabs');
|
||||
@ -73,9 +68,10 @@ export const useTabStore = defineStore(SetupStoreId.Tab, () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* add tab
|
||||
* @param route tab route
|
||||
* @param active whether to activate the added tab
|
||||
* Add tab
|
||||
*
|
||||
* @param route Tab route
|
||||
* @param active Whether to activate the added tab
|
||||
*/
|
||||
function addTab(route: App.Global.TabRoute, active = true) {
|
||||
const tab = getTabByRoute(route);
|
||||
@ -92,8 +88,9 @@ export const useTabStore = defineStore(SetupStoreId.Tab, () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* remove tab
|
||||
* @param tabId tab id
|
||||
* Remove tab
|
||||
*
|
||||
* @param tabId Tab id
|
||||
*/
|
||||
async function removeTab(tabId: string) {
|
||||
const isRemoveActiveTab = activeTabId.value === tabId;
|
||||
@ -117,8 +114,9 @@ export const useTabStore = defineStore(SetupStoreId.Tab, () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* clear tabs
|
||||
* @param excludes exclude tab ids
|
||||
* Clear tabs
|
||||
*
|
||||
* @param excludes Exclude tab ids
|
||||
*/
|
||||
async function clearTabs(excludes: string[] = []) {
|
||||
const remainTabIds = [...getFixedTabIds(tabs.value), ...excludes];
|
||||
@ -143,7 +141,8 @@ export const useTabStore = defineStore(SetupStoreId.Tab, () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* switch route by tab
|
||||
* Switch route by tab
|
||||
*
|
||||
* @param tab
|
||||
*/
|
||||
async function switchRouteByTab(tab: App.Global.Tab) {
|
||||
@ -154,7 +153,8 @@ export const useTabStore = defineStore(SetupStoreId.Tab, () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* clear left tabs
|
||||
* Clear left tabs
|
||||
*
|
||||
* @param tabId
|
||||
*/
|
||||
async function clearLeftTabs(tabId: string) {
|
||||
@ -167,7 +167,8 @@ export const useTabStore = defineStore(SetupStoreId.Tab, () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* clear right tabs
|
||||
* Clear right tabs
|
||||
*
|
||||
* @param tabId
|
||||
*/
|
||||
async function clearRightTabs(tabId: string) {
|
||||
@ -180,10 +181,11 @@ export const useTabStore = defineStore(SetupStoreId.Tab, () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* set new label of tab
|
||||
* @param label new tab label
|
||||
* @param tabId tab id
|
||||
* Set new label of tab
|
||||
*
|
||||
* @default activeTabId
|
||||
* @param label New tab label
|
||||
* @param tabId Tab id
|
||||
*/
|
||||
function setTabLabel(label: string, tabId?: string) {
|
||||
const id = tabId || activeTabId.value;
|
||||
@ -195,9 +197,10 @@ export const useTabStore = defineStore(SetupStoreId.Tab, () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* reset tab label
|
||||
* @param tabId tab id
|
||||
* Reset tab label
|
||||
*
|
||||
* @default activeTabId
|
||||
* @param tabId Tab id
|
||||
*/
|
||||
function resetTabLabel(tabId?: string) {
|
||||
const id = tabId || activeTabId.value;
|
||||
@ -209,7 +212,8 @@ export const useTabStore = defineStore(SetupStoreId.Tab, () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* is tab retain
|
||||
* Is tab retain
|
||||
*
|
||||
* @param tabId
|
||||
*/
|
||||
function isTabRetain(tabId: string) {
|
||||
@ -220,9 +224,7 @@ export const useTabStore = defineStore(SetupStoreId.Tab, () => {
|
||||
return fixedTabIds.includes(tabId);
|
||||
}
|
||||
|
||||
/**
|
||||
* update tabs by locale
|
||||
*/
|
||||
/** Update tabs by locale */
|
||||
function updateTabsByLocale() {
|
||||
tabs.value = updateTabsByI18nKey(tabs.value);
|
||||
|
||||
@ -231,9 +233,7 @@ export const useTabStore = defineStore(SetupStoreId.Tab, () => {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cache tabs
|
||||
*/
|
||||
/** Cache tabs */
|
||||
function cacheTabs() {
|
||||
if (!themeStore.tab.cache) return;
|
||||
|
||||
@ -246,9 +246,7 @@ export const useTabStore = defineStore(SetupStoreId.Tab, () => {
|
||||
});
|
||||
|
||||
return {
|
||||
/**
|
||||
* all tabs
|
||||
*/
|
||||
/** All tabs */
|
||||
tabs: allTabs,
|
||||
activeTabId,
|
||||
initHomeTab,
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
import type { Router } from 'vue-router';
|
||||
import type { RouteMap, LastLevelRouteKey } from '@elegant-router/types';
|
||||
import type { LastLevelRouteKey, RouteMap } from '@elegant-router/types';
|
||||
import { $t } from '@/locales';
|
||||
import { getRoutePath } from '@/router/elegant/transform';
|
||||
|
||||
/**
|
||||
* get all tabs
|
||||
* @param tabs tabs
|
||||
* @param homeTab home tab
|
||||
* Get all tabs
|
||||
*
|
||||
* @param tabs Tabs
|
||||
* @param homeTab Home tab
|
||||
*/
|
||||
export function getAllTabs(tabs: App.Global.Tab[], homeTab?: App.Global.Tab) {
|
||||
if (!homeTab) {
|
||||
@ -23,7 +24,8 @@ export function getAllTabs(tabs: App.Global.Tab[], homeTab?: App.Global.Tab) {
|
||||
}
|
||||
|
||||
/**
|
||||
* get tab id by route
|
||||
* Get tab id by route
|
||||
*
|
||||
* @param route
|
||||
*/
|
||||
export function getTabIdByRoute(route: App.Global.TabRoute) {
|
||||
@ -42,7 +44,8 @@ export function getTabIdByRoute(route: App.Global.TabRoute) {
|
||||
}
|
||||
|
||||
/**
|
||||
* get tab by route
|
||||
* Get tab by route
|
||||
*
|
||||
* @param route
|
||||
*/
|
||||
export function getTabByRoute(route: App.Global.TabRoute) {
|
||||
@ -67,7 +70,8 @@ export function getTabByRoute(route: App.Global.TabRoute) {
|
||||
}
|
||||
|
||||
/**
|
||||
* get default home tab
|
||||
* Get default home tab
|
||||
*
|
||||
* @param router
|
||||
*/
|
||||
export function getDefaultHomeTab(router: Router) {
|
||||
@ -93,7 +97,8 @@ export function getDefaultHomeTab(router: Router) {
|
||||
}
|
||||
|
||||
/**
|
||||
* is tab in tabs
|
||||
* Is tab in tabs
|
||||
*
|
||||
* @param tab
|
||||
* @param tabs
|
||||
*/
|
||||
@ -102,7 +107,8 @@ export function isTabInTabs(tabId: string, tabs: App.Global.Tab[]) {
|
||||
}
|
||||
|
||||
/**
|
||||
* filter tabs by id
|
||||
* Filter tabs by id
|
||||
*
|
||||
* @param tabId
|
||||
* @param tabs
|
||||
*/
|
||||
@ -111,7 +117,8 @@ export function filterTabsById(tabId: string, tabs: App.Global.Tab[]) {
|
||||
}
|
||||
|
||||
/**
|
||||
* filter tabs by ids
|
||||
* Filter tabs by ids
|
||||
*
|
||||
* @param tabIds
|
||||
* @param tabs
|
||||
*/
|
||||
@ -120,7 +127,8 @@ export function filterTabsByIds(tabIds: string[], tabs: App.Global.Tab[]) {
|
||||
}
|
||||
|
||||
/**
|
||||
* get fixed tabs
|
||||
* Get fixed tabs
|
||||
*
|
||||
* @param tabs
|
||||
*/
|
||||
export function getFixedTabs(tabs: App.Global.Tab[]) {
|
||||
@ -128,7 +136,8 @@ export function getFixedTabs(tabs: App.Global.Tab[]) {
|
||||
}
|
||||
|
||||
/**
|
||||
* get fixed tab ids
|
||||
* Get fixed tab ids
|
||||
*
|
||||
* @param tabs
|
||||
*/
|
||||
export function getFixedTabIds(tabs: App.Global.Tab[]) {
|
||||
@ -138,7 +147,8 @@ export function getFixedTabIds(tabs: App.Global.Tab[]) {
|
||||
}
|
||||
|
||||
/**
|
||||
* update tabs label
|
||||
* Update tabs label
|
||||
*
|
||||
* @param tabs
|
||||
*/
|
||||
function updateTabsLabel(tabs: App.Global.Tab[]) {
|
||||
@ -149,7 +159,8 @@ function updateTabsLabel(tabs: App.Global.Tab[]) {
|
||||
}
|
||||
|
||||
/**
|
||||
* update tab by i18n key
|
||||
* Update tab by i18n key
|
||||
*
|
||||
* @param tab
|
||||
*/
|
||||
export function updateTabByI18nKey(tab: App.Global.Tab) {
|
||||
@ -162,7 +173,8 @@ export function updateTabByI18nKey(tab: App.Global.Tab) {
|
||||
}
|
||||
|
||||
/**
|
||||
* update tabs by i18n key
|
||||
* Update tabs by i18n key
|
||||
*
|
||||
* @param tabs
|
||||
*/
|
||||
export function updateTabsByI18nKey(tabs: App.Global.Tab[]) {
|
||||
|
||||
@ -1,26 +1,20 @@
|
||||
import { ref, computed, effectScope, onScopeDispose, watch, toRefs } from 'vue';
|
||||
import { computed, effectScope, onScopeDispose, ref, toRefs, watch } from 'vue';
|
||||
import type { Ref } from 'vue';
|
||||
import { defineStore } from 'pinia';
|
||||
import { usePreferredColorScheme, useEventListener } from '@vueuse/core';
|
||||
import { useEventListener, usePreferredColorScheme } from '@vueuse/core';
|
||||
import { SetupStoreId } from '@/enum';
|
||||
import { localStg } from '@/utils/storage';
|
||||
import { createThemeToken, initThemeSettings, addThemeVarsToHtml, toggleCssDarkMode, getNaiveTheme } from './shared';
|
||||
import { addThemeVarsToHtml, createThemeToken, getNaiveTheme, initThemeSettings, toggleCssDarkMode } from './shared';
|
||||
|
||||
/**
|
||||
* theme store
|
||||
*/
|
||||
/** Theme store */
|
||||
export const useThemeStore = defineStore(SetupStoreId.Theme, () => {
|
||||
const scope = effectScope();
|
||||
const osTheme = usePreferredColorScheme();
|
||||
|
||||
/**
|
||||
* theme settings
|
||||
*/
|
||||
/** Theme settings */
|
||||
const settings: Ref<App.Theme.ThemeSetting> = ref(initThemeSettings());
|
||||
|
||||
/**
|
||||
* dark mode
|
||||
*/
|
||||
/** Dark mode */
|
||||
const darkMode = computed(() => {
|
||||
if (settings.value.themeScheme === 'auto') {
|
||||
return osTheme.value === 'dark';
|
||||
@ -28,9 +22,7 @@ export const useThemeStore = defineStore(SetupStoreId.Theme, () => {
|
||||
return settings.value.themeScheme === 'dark';
|
||||
});
|
||||
|
||||
/**
|
||||
* theme colors
|
||||
*/
|
||||
/** Theme colors */
|
||||
const themeColors = computed(() => {
|
||||
const { themeColor, otherColor, isInfoFollowPrimary } = settings.value;
|
||||
const colors: App.Theme.ThemeColor = {
|
||||
@ -41,20 +33,17 @@ export const useThemeStore = defineStore(SetupStoreId.Theme, () => {
|
||||
return colors;
|
||||
});
|
||||
|
||||
/**
|
||||
* naive theme
|
||||
*/
|
||||
/** Naive theme */
|
||||
const naiveTheme = computed(() => getNaiveTheme(themeColors.value));
|
||||
|
||||
/**
|
||||
* settings json
|
||||
* @description it is for copy settings
|
||||
* Settings json
|
||||
*
|
||||
* It is for copy settings
|
||||
*/
|
||||
const settingsJson = computed(() => JSON.stringify(settings.value));
|
||||
|
||||
/**
|
||||
* reset store
|
||||
*/
|
||||
/** Reset store */
|
||||
function resetStore() {
|
||||
const themeStore = useThemeStore();
|
||||
|
||||
@ -62,16 +51,15 @@ export const useThemeStore = defineStore(SetupStoreId.Theme, () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* set theme scheme
|
||||
* Set theme scheme
|
||||
*
|
||||
* @param themeScheme
|
||||
*/
|
||||
function setThemeScheme(themeScheme: UnionKey.ThemeScheme) {
|
||||
settings.value.themeScheme = themeScheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* toggle theme scheme
|
||||
*/
|
||||
/** Toggle theme scheme */
|
||||
function toggleThemeScheme() {
|
||||
const themeSchemes: UnionKey.ThemeScheme[] = ['light', 'dark', 'auto'];
|
||||
|
||||
@ -85,9 +73,10 @@ export const useThemeStore = defineStore(SetupStoreId.Theme, () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* update theme colors
|
||||
* @param key theme color key
|
||||
* @param color theme color
|
||||
* Update theme colors
|
||||
*
|
||||
* @param key Theme color key
|
||||
* @param color Theme color
|
||||
*/
|
||||
function updateThemeColors(key: App.Theme.ThemeColorKey, color: string) {
|
||||
if (key === 'primary') {
|
||||
@ -98,24 +87,21 @@ export const useThemeStore = defineStore(SetupStoreId.Theme, () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* set theme layout
|
||||
* @param mode theme layout mode
|
||||
* Set theme layout
|
||||
*
|
||||
* @param mode Theme layout mode
|
||||
*/
|
||||
function setThemeLayout(mode: UnionKey.ThemeLayoutMode) {
|
||||
settings.value.layout.mode = mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* setup theme vars to html
|
||||
*/
|
||||
/** Setup theme vars to html */
|
||||
function setupThemeVarsToHtml() {
|
||||
const { themeTokens, darkThemeTokens } = createThemeToken(themeColors.value);
|
||||
addThemeVarsToHtml(themeTokens, darkThemeTokens);
|
||||
}
|
||||
|
||||
/**
|
||||
* cache theme settings
|
||||
*/
|
||||
/** Cache theme settings */
|
||||
function cacheThemeSettings() {
|
||||
const isProd = import.meta.env.PROD;
|
||||
|
||||
@ -150,9 +136,7 @@ export const useThemeStore = defineStore(SetupStoreId.Theme, () => {
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* on scope dispose
|
||||
*/
|
||||
/** On scope dispose */
|
||||
onScopeDispose(() => {
|
||||
scope.stop();
|
||||
});
|
||||
|
||||
@ -1,15 +1,13 @@
|
||||
import type { GlobalThemeOverrides } from 'naive-ui';
|
||||
import { getColorPalette, getColorByColorPaletteNumber } from '@sa/color-palette';
|
||||
import { getRgbOfColor, addColorAlpha } from '@sa/utils';
|
||||
import { themeSettings, overrideThemeSettings } from '@/theme/settings';
|
||||
import { getColorByColorPaletteNumber, getColorPalette } from '@sa/color-palette';
|
||||
import { addColorAlpha, getRgbOfColor } from '@sa/utils';
|
||||
import { overrideThemeSettings, themeSettings } from '@/theme/settings';
|
||||
import { themeVars } from '@/theme/vars';
|
||||
import { localStg } from '@/utils/storage';
|
||||
|
||||
const DARK_CLASS = 'dark';
|
||||
|
||||
/**
|
||||
* init theme settings
|
||||
*/
|
||||
/** Init theme settings */
|
||||
export function initThemeSettings() {
|
||||
const isProd = import.meta.env.PROD;
|
||||
|
||||
@ -32,8 +30,9 @@ export function initThemeSettings() {
|
||||
}
|
||||
|
||||
/**
|
||||
* create theme token
|
||||
* @param colors theme colors
|
||||
* Create theme token
|
||||
*
|
||||
* @param colors Theme colors
|
||||
*/
|
||||
export function createThemeToken(colors: App.Theme.ThemeColor) {
|
||||
const paletteColors = createThemePaletteColors(colors);
|
||||
@ -73,8 +72,9 @@ export function createThemeToken(colors: App.Theme.ThemeColor) {
|
||||
}
|
||||
|
||||
/**
|
||||
* create theme palette colors
|
||||
* @param colors theme colors
|
||||
* Create theme palette colors
|
||||
*
|
||||
* @param colors Theme colors
|
||||
*/
|
||||
function createThemePaletteColors(colors: App.Theme.ThemeColor) {
|
||||
const colorKeys = Object.keys(colors) as App.Theme.ThemeColorKey[];
|
||||
@ -94,8 +94,9 @@ function createThemePaletteColors(colors: App.Theme.ThemeColor) {
|
||||
}
|
||||
|
||||
/**
|
||||
* get css var by tokens
|
||||
* @param tokens theme base tokens
|
||||
* Get css var by tokens
|
||||
*
|
||||
* @param tokens Theme base tokens
|
||||
*/
|
||||
function getCssVarByTokens(tokens: App.Theme.BaseToken) {
|
||||
const styles: string[] = [];
|
||||
@ -129,7 +130,8 @@ function getCssVarByTokens(tokens: App.Theme.BaseToken) {
|
||||
}
|
||||
|
||||
/**
|
||||
* add theme vars to html
|
||||
* Add theme vars to html
|
||||
*
|
||||
* @param tokens
|
||||
*/
|
||||
export function addThemeVarsToHtml(tokens: App.Theme.BaseToken, darkTokens: App.Theme.BaseToken) {
|
||||
@ -150,14 +152,15 @@ export function addThemeVarsToHtml(tokens: App.Theme.BaseToken, darkTokens: App.
|
||||
|
||||
const style = document.createElement('style');
|
||||
|
||||
style.innerText = css + darkCss;
|
||||
style.textContent = css + darkCss;
|
||||
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
/**
|
||||
* toggle css dark mode
|
||||
* @param darkMode is dark mode
|
||||
* Toggle css dark mode
|
||||
*
|
||||
* @param darkMode Is dark mode
|
||||
*/
|
||||
export function toggleCssDarkMode(darkMode = false) {
|
||||
function addDarkClass() {
|
||||
@ -184,8 +187,9 @@ interface NaiveColorAction {
|
||||
}
|
||||
|
||||
/**
|
||||
* get naive theme colors
|
||||
* @param colors theme colors
|
||||
* Get naive theme colors
|
||||
*
|
||||
* @param colors Theme colors
|
||||
*/
|
||||
function getNaiveThemeColors(colors: App.Theme.ThemeColor) {
|
||||
const colorActions: NaiveColorAction[] = [
|
||||
@ -212,8 +216,9 @@ function getNaiveThemeColors(colors: App.Theme.ThemeColor) {
|
||||
}
|
||||
|
||||
/**
|
||||
* get naive theme
|
||||
* @param colors theme colors
|
||||
* Get naive theme
|
||||
*
|
||||
* @param colors Theme colors
|
||||
*/
|
||||
export function getNaiveTheme(colors: App.Theme.ThemeColor) {
|
||||
const { primary: colorLoading } = colors;
|
||||
|
||||
@ -3,7 +3,8 @@ import { cloneDeep } from 'lodash-es';
|
||||
import { SetupStoreId } from '@/enum';
|
||||
|
||||
/**
|
||||
* the plugin reset the state of the store which is written by setup syntax
|
||||
* The plugin reset the state of the store which is written by setup syntax
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
export function resetSetupStore(context: PiniaPluginContext) {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
@import "./reset.css";
|
||||
@import "./nprogress.css";
|
||||
@import "./transition.css";
|
||||
@import './reset.css';
|
||||
@import './nprogress.css';
|
||||
@import './transition.css';
|
||||
|
||||
html,
|
||||
body,
|
||||
|
||||
@ -30,16 +30,16 @@ html {
|
||||
system-ui,
|
||||
-apple-system,
|
||||
BlinkMacSystemFont,
|
||||
"Segoe UI",
|
||||
'Segoe UI',
|
||||
Roboto,
|
||||
"Helvetica Neue",
|
||||
'Helvetica Neue',
|
||||
Arial,
|
||||
"Noto Sans",
|
||||
'Noto Sans',
|
||||
sans-serif,
|
||||
"Apple Color Emoji",
|
||||
"Segoe UI Emoji",
|
||||
"Segoe UI Symbol",
|
||||
"Noto Color Emoji"; /* 4 */
|
||||
'Apple Color Emoji',
|
||||
'Segoe UI Emoji',
|
||||
'Segoe UI Symbol',
|
||||
'Noto Color Emoji'; /* 4 */
|
||||
}
|
||||
|
||||
/*
|
||||
@ -113,8 +113,7 @@ code,
|
||||
kbd,
|
||||
samp,
|
||||
pre {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
|
||||
"Liberation Mono", "Courier New", monospace; /* 1 */
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
@ -195,9 +194,9 @@ select {
|
||||
*/
|
||||
|
||||
button,
|
||||
[type="button"],
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
[type='button'],
|
||||
[type='reset'],
|
||||
[type='submit'] {
|
||||
-webkit-appearance: button; /* 1 */
|
||||
/* background-color: transparent; */
|
||||
background-image: none; /* 2 */
|
||||
@ -241,7 +240,7 @@ Correct the cursor style of increment and decrement buttons in Safari.
|
||||
2. Correct the outline style in Safari.
|
||||
*/
|
||||
|
||||
[type="search"] {
|
||||
[type='search'] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
outline-offset: -2px; /* 2 */
|
||||
}
|
||||
@ -333,7 +332,7 @@ Set the default cursor for buttons.
|
||||
*/
|
||||
|
||||
button,
|
||||
[role="button"] {
|
||||
[role='button'] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
@ -1 +1 @@
|
||||
@import "./scrollbar.scss";
|
||||
@import './scrollbar.scss';
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
/**
|
||||
* default theme settings
|
||||
*/
|
||||
/** Default theme settings */
|
||||
export const themeSettings: App.Theme.ThemeSetting = {
|
||||
themeScheme: 'light',
|
||||
themeColor: '#646cff',
|
||||
@ -50,7 +48,8 @@ export const themeSettings: App.Theme.ThemeSetting = {
|
||||
};
|
||||
|
||||
/**
|
||||
* override theme settings
|
||||
* @description if publish new version, use `overrideThemeSettings` to override certain theme settings
|
||||
* Override theme settings
|
||||
*
|
||||
* If publish new version, use `overrideThemeSettings` to override certain theme settings
|
||||
*/
|
||||
export const overrideThemeSettings: Partial<App.Theme.ThemeSetting> = {};
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
/**
|
||||
* create color palette vars
|
||||
*/
|
||||
/** Create color palette vars */
|
||||
function createColorPaletteVars() {
|
||||
const colors: App.Theme.ThemeColorKey[] = ['primary', 'info', 'success', 'warning', 'error'];
|
||||
const colorPaletteNumbers: App.Theme.ColorPaletteNumber[] = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
|
||||
@ -19,9 +17,7 @@ function createColorPaletteVars() {
|
||||
|
||||
const colorPaletteVars = createColorPaletteVars();
|
||||
|
||||
/**
|
||||
* theme vars
|
||||
*/
|
||||
/** Theme vars */
|
||||
export const themeVars: App.Theme.ThemeToken = {
|
||||
colors: {
|
||||
...colorPaletteVars,
|
||||
|
||||
15
src/typings/api.d.ts
vendored
15
src/typings/api.d.ts
vendored
@ -1,11 +1,13 @@
|
||||
/**
|
||||
* namespace Api
|
||||
* @description all backend api type
|
||||
* Namespace Api
|
||||
*
|
||||
* All backend api type
|
||||
*/
|
||||
declare namespace Api {
|
||||
/**
|
||||
* namespace Auth
|
||||
* @description backend api module: "auth"
|
||||
* Namespace Auth
|
||||
*
|
||||
* Backend api module: "auth"
|
||||
*/
|
||||
namespace Auth {
|
||||
interface LoginToken {
|
||||
@ -21,8 +23,9 @@ declare namespace Api {
|
||||
}
|
||||
|
||||
/**
|
||||
* namespace Route
|
||||
* @description backend api module: "route"
|
||||
* Namespace Route
|
||||
*
|
||||
* Backend api module: "route"
|
||||
*/
|
||||
namespace Route {
|
||||
type ElegantConstRoute = import('@elegant-router/types').ElegantConstRoute;
|
||||
|
||||
310
src/typings/app.d.ts
vendored
310
src/typings/app.d.ts
vendored
@ -1,16 +1,10 @@
|
||||
/**
|
||||
* the global namespace for the app
|
||||
*/
|
||||
/** The global namespace for the app */
|
||||
declare namespace App {
|
||||
/**
|
||||
* theme namespace
|
||||
*/
|
||||
/** Theme namespace */
|
||||
namespace Theme {
|
||||
type ColorPaletteNumber = import('@sa/color-palette').ColorPaletteNumber;
|
||||
|
||||
/**
|
||||
* theme token
|
||||
*/
|
||||
/** Theme token */
|
||||
type ThemeToken = {
|
||||
colors: ThemeTokenColor;
|
||||
boxShadow: {
|
||||
@ -20,148 +14,83 @@ declare namespace App {
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* theme setting
|
||||
*/
|
||||
/** Theme setting */
|
||||
interface ThemeSetting {
|
||||
/**
|
||||
* theme scheme
|
||||
*/
|
||||
/** Theme scheme */
|
||||
themeScheme: UnionKey.ThemeScheme;
|
||||
/**
|
||||
* theme color
|
||||
*/
|
||||
/** Theme color */
|
||||
themeColor: string;
|
||||
/**
|
||||
* other color
|
||||
*/
|
||||
/** Other color */
|
||||
otherColor: OtherColor;
|
||||
/**
|
||||
* whether info color is followed by the primary color
|
||||
*/
|
||||
/** Whether info color is followed by the primary color */
|
||||
isInfoFollowPrimary: boolean;
|
||||
/**
|
||||
* layout
|
||||
*/
|
||||
/** Layout */
|
||||
layout: {
|
||||
/**
|
||||
* layout mode
|
||||
*/
|
||||
/** Layout mode */
|
||||
mode: UnionKey.ThemeLayoutMode;
|
||||
/**
|
||||
* scroll mode
|
||||
*/
|
||||
/** Scroll mode */
|
||||
scrollMode: UnionKey.ThemeScrollMode;
|
||||
};
|
||||
/**
|
||||
* page
|
||||
*/
|
||||
/** Page */
|
||||
page: {
|
||||
/**
|
||||
* whether to show the page transition
|
||||
*/
|
||||
/** Whether to show the page transition */
|
||||
animate: boolean;
|
||||
/**
|
||||
* page animate mode
|
||||
*/
|
||||
/** Page animate mode */
|
||||
animateMode: UnionKey.ThemePageAnimateMode;
|
||||
};
|
||||
/**
|
||||
* header
|
||||
*/
|
||||
/** Header */
|
||||
header: {
|
||||
/**
|
||||
* header height
|
||||
*/
|
||||
/** Header height */
|
||||
height: number;
|
||||
/**
|
||||
* header breadcrumb
|
||||
*/
|
||||
/** Header breadcrumb */
|
||||
breadcrumb: {
|
||||
/**
|
||||
* whether to show the breadcrumb
|
||||
*/
|
||||
/** Whether to show the breadcrumb */
|
||||
visible: boolean;
|
||||
/**
|
||||
* whether to show the breadcrumb icon
|
||||
*/
|
||||
/** Whether to show the breadcrumb icon */
|
||||
showIcon: boolean;
|
||||
};
|
||||
};
|
||||
/**
|
||||
* tab
|
||||
*/
|
||||
/** Tab */
|
||||
tab: {
|
||||
/**
|
||||
* whether to show the tab
|
||||
*/
|
||||
/** Whether to show the tab */
|
||||
visible: boolean;
|
||||
/**
|
||||
* whether to cache the tab
|
||||
* @description if cache, the tabs will get from the local storage when the page is refreshed
|
||||
* Whether to cache the tab
|
||||
*
|
||||
* If cache, the tabs will get from the local storage when the page is refreshed
|
||||
*/
|
||||
cache: boolean;
|
||||
/**
|
||||
* tab height
|
||||
*/
|
||||
/** Tab height */
|
||||
height: number;
|
||||
/**
|
||||
* tab mode
|
||||
*/
|
||||
/** Tab mode */
|
||||
mode: UnionKey.ThemeTabMode;
|
||||
};
|
||||
/**
|
||||
* fixed header and tab
|
||||
*/
|
||||
/** Fixed header and tab */
|
||||
fixedHeaderAndTab: boolean;
|
||||
/**
|
||||
* sider
|
||||
*/
|
||||
/** Sider */
|
||||
sider: {
|
||||
/**
|
||||
* inverted sider
|
||||
*/
|
||||
/** Inverted sider */
|
||||
inverted: boolean;
|
||||
/**
|
||||
* sider width
|
||||
*/
|
||||
/** Sider width */
|
||||
width: number;
|
||||
/**
|
||||
* collapsed sider width
|
||||
*/
|
||||
/** Collapsed sider width */
|
||||
collapsedWidth: number;
|
||||
/**
|
||||
* sider width when the layout is 'vertical-mix' or 'horizontal-mix'
|
||||
*/
|
||||
/** Sider width when the layout is 'vertical-mix' or 'horizontal-mix' */
|
||||
mixWidth: number;
|
||||
/**
|
||||
* collapsed sider width when the layout is 'vertical-mix' or 'horizontal-mix'
|
||||
*/
|
||||
/** Collapsed sider width when the layout is 'vertical-mix' or 'horizontal-mix' */
|
||||
mixCollapsedWidth: number;
|
||||
/**
|
||||
* child menu width when the layout is 'vertical-mix' or 'horizontal-mix'
|
||||
*/
|
||||
/** Child menu width when the layout is 'vertical-mix' or 'horizontal-mix' */
|
||||
mixChildMenuWidth: number;
|
||||
};
|
||||
/**
|
||||
* footer
|
||||
*/
|
||||
/** Footer */
|
||||
footer: {
|
||||
/**
|
||||
* whether to show the footer
|
||||
*/
|
||||
/** Whether to show the footer */
|
||||
visible: boolean;
|
||||
/**
|
||||
* whether fixed the footer
|
||||
*/
|
||||
/** Whether fixed the footer */
|
||||
fixed: boolean;
|
||||
/**
|
||||
* footer height
|
||||
*/
|
||||
/** Footer height */
|
||||
height: number;
|
||||
/**
|
||||
* whether float the footer to the right when the layout is 'horizontal-mix'
|
||||
*/
|
||||
/** Whether float the footer to the right when the layout is 'horizontal-mix' */
|
||||
right: boolean;
|
||||
};
|
||||
}
|
||||
@ -195,9 +124,7 @@ declare namespace App {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* global namespace
|
||||
*/
|
||||
/** Global namespace */
|
||||
namespace Global {
|
||||
type VNode = import('vue').VNode;
|
||||
type RouteLocationNormalizedLoaded = import('vue-router').RouteLocationNormalizedLoaded;
|
||||
@ -206,56 +133,35 @@ declare namespace App {
|
||||
type RoutePath = import('@elegant-router/types').RoutePath;
|
||||
type LastLevelRouteKey = import('@elegant-router/types').LastLevelRouteKey;
|
||||
|
||||
/**
|
||||
* the global header props
|
||||
*/
|
||||
/** The global header props */
|
||||
interface HeaderProps {
|
||||
/**
|
||||
* whether to show the logo
|
||||
*/
|
||||
/** Whether to show the logo */
|
||||
showLogo?: boolean;
|
||||
/**
|
||||
* whether to show the menu toggler
|
||||
*/
|
||||
/** Whether to show the menu toggler */
|
||||
showMenuToggler?: boolean;
|
||||
/**
|
||||
* whether to show the menu
|
||||
*/
|
||||
/** Whether to show the menu */
|
||||
showMenu?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* the global menu
|
||||
*/
|
||||
/** The global menu */
|
||||
interface Menu {
|
||||
/**
|
||||
* the menu key
|
||||
* @description equal to the route key
|
||||
* The menu key
|
||||
*
|
||||
* Equal to the route key
|
||||
*/
|
||||
key: string;
|
||||
/**
|
||||
* the menu label
|
||||
*/
|
||||
/** The menu label */
|
||||
label: string;
|
||||
/**
|
||||
* the menu i18n key
|
||||
*/
|
||||
/** The menu i18n key */
|
||||
i18nKey?: I18n.I18nKey;
|
||||
/**
|
||||
* the route key
|
||||
*/
|
||||
/** The route key */
|
||||
routeKey: RouteKey;
|
||||
/**
|
||||
* the route path
|
||||
*/
|
||||
/** The route path */
|
||||
routePath: RoutePath;
|
||||
/**
|
||||
* the menu icon
|
||||
*/
|
||||
/** The menu icon */
|
||||
icon?: () => VNode;
|
||||
/**
|
||||
* the menu children
|
||||
*/
|
||||
/** The menu children */
|
||||
children?: Menu[];
|
||||
}
|
||||
|
||||
@ -263,75 +169,57 @@ declare namespace App {
|
||||
options?: Breadcrumb[];
|
||||
};
|
||||
|
||||
/**
|
||||
* tab route
|
||||
*/
|
||||
/** Tab route */
|
||||
type TabRoute = Pick<RouteLocationNormalizedLoaded, 'name' | 'path' | 'meta'> &
|
||||
Partial<Pick<RouteLocationNormalizedLoaded, 'fullPath' | 'query'>>;
|
||||
|
||||
/**
|
||||
* the global tab
|
||||
*/
|
||||
/** The global tab */
|
||||
type Tab = {
|
||||
/**
|
||||
* the tab id
|
||||
*/
|
||||
/** The tab id */
|
||||
id: string;
|
||||
/**
|
||||
* the tab label
|
||||
*/
|
||||
/** The tab label */
|
||||
label: string;
|
||||
/**
|
||||
* the new tab label
|
||||
* @description if set, the tab label will be replaced by this value
|
||||
* The new tab label
|
||||
*
|
||||
* If set, the tab label will be replaced by this value
|
||||
*/
|
||||
newLabel?: string;
|
||||
/**
|
||||
* the tab route key
|
||||
*/
|
||||
/** The tab route key */
|
||||
routeKey: LastLevelRouteKey;
|
||||
/**
|
||||
* the tab route path
|
||||
*/
|
||||
/** The tab route path */
|
||||
routePath: RouteMap[LastLevelRouteKey];
|
||||
/**
|
||||
* the tab route full path
|
||||
*/
|
||||
/** The tab route full path */
|
||||
fullPath: string;
|
||||
/**
|
||||
* the tab fixed index
|
||||
*/
|
||||
/** The tab fixed index */
|
||||
fixedIndex?: number;
|
||||
/**
|
||||
* tab icon
|
||||
* @description iconify icon
|
||||
* Tab icon
|
||||
*
|
||||
* Iconify icon
|
||||
*/
|
||||
icon?: string;
|
||||
/**
|
||||
* tab local icon
|
||||
* @description local icon
|
||||
* Tab local icon
|
||||
*
|
||||
* Local icon
|
||||
*/
|
||||
localIcon?: string;
|
||||
/**
|
||||
* i18n key
|
||||
*/
|
||||
/** I18n key */
|
||||
i18nKey?: I18n.I18nKey;
|
||||
};
|
||||
|
||||
/**
|
||||
* form rule
|
||||
*/
|
||||
/** Form rule */
|
||||
type FormRule = import('naive-ui').FormItemRule;
|
||||
|
||||
/**
|
||||
* the global dropdown key
|
||||
*/
|
||||
/** The global dropdown key */
|
||||
type DropdownKey = 'closeCurrent' | 'closeOther' | 'closeLeft' | 'closeRight' | 'closeAll';
|
||||
}
|
||||
|
||||
/**
|
||||
* i18n namespace
|
||||
* @description locales type
|
||||
* I18n namespace
|
||||
*
|
||||
* Locales type
|
||||
*/
|
||||
namespace I18n {
|
||||
type RouteKey = import('@elegant-router/types').RouteKey;
|
||||
@ -514,54 +402,32 @@ declare namespace App {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* service namespace
|
||||
*/
|
||||
/** Service namespace */
|
||||
namespace Service {
|
||||
/**
|
||||
* the backend service env type
|
||||
*/
|
||||
/** The backend service env type */
|
||||
type EnvType = 'dev' | 'test' | 'prod';
|
||||
|
||||
/**
|
||||
* other baseURL key
|
||||
*/
|
||||
/** Other baseURL key */
|
||||
type OtherBaseURLKey = 'demo';
|
||||
|
||||
/**
|
||||
* the backend service config
|
||||
*/
|
||||
/** The backend service config */
|
||||
interface ServiceConfig<T extends OtherBaseURLKey = OtherBaseURLKey> {
|
||||
/**
|
||||
* the backend service base url
|
||||
*/
|
||||
/** The backend service base url */
|
||||
baseURL: string;
|
||||
/**
|
||||
* other backend service base url map
|
||||
*/
|
||||
/** Other backend service base url map */
|
||||
otherBaseURL: Record<T, string>;
|
||||
}
|
||||
|
||||
/**
|
||||
* the backend service config map
|
||||
*/
|
||||
/** The backend service config map */
|
||||
type ServiceConfigMap = Record<EnvType, ServiceConfig>;
|
||||
|
||||
/**
|
||||
* the backend service response data
|
||||
*/
|
||||
/** The backend service response data */
|
||||
type Response<T = unknown> = {
|
||||
/**
|
||||
* the backend service response code
|
||||
*/
|
||||
/** The backend service response code */
|
||||
code: string;
|
||||
/**
|
||||
* the backend service response message
|
||||
*/
|
||||
/** The backend service response message */
|
||||
message: string;
|
||||
/**
|
||||
* the backend service response data
|
||||
*/
|
||||
/** The backend service response data */
|
||||
data: T;
|
||||
};
|
||||
}
|
||||
|
||||
23
src/typings/common.d.ts
vendored
23
src/typings/common.d.ts
vendored
@ -1,25 +1,18 @@
|
||||
/**
|
||||
* the common type namespace
|
||||
*/
|
||||
/** The common type namespace */
|
||||
declare namespace Common {
|
||||
/**
|
||||
* the strategic pattern
|
||||
*/
|
||||
/** The strategic pattern */
|
||||
interface StrategicPattern {
|
||||
/**
|
||||
* the condition
|
||||
*/
|
||||
/** The condition */
|
||||
condition: boolean;
|
||||
/**
|
||||
* if the condition is true, then call the action function
|
||||
*/
|
||||
/** If the condition is true, then call the action function */
|
||||
callback: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* the option type
|
||||
* @property value: the option value
|
||||
* @property label: the option label
|
||||
* The option type
|
||||
*
|
||||
* @property value: The option value
|
||||
* @property label: The option label
|
||||
*/
|
||||
type Option<K> = { value: K; label: string };
|
||||
|
||||
|
||||
75
src/typings/env.d.ts
vendored
75
src/typings/env.d.ts
vendored
@ -1,74 +1,65 @@
|
||||
/**
|
||||
* namespace Env
|
||||
* @description it is used to declare the type of the import.meta object
|
||||
* Namespace Env
|
||||
*
|
||||
* It is used to declare the type of the import.meta object
|
||||
*/
|
||||
declare namespace Env {
|
||||
/**
|
||||
* the router history mode
|
||||
*/
|
||||
/** The router history mode */
|
||||
type RouterHistoryMode = 'hash' | 'history' | 'memory';
|
||||
|
||||
/**
|
||||
* interface for import.meta
|
||||
*/
|
||||
/** Interface for import.meta */
|
||||
interface ImportMeta extends ImportMetaEnv {
|
||||
/**
|
||||
* the base url of the application
|
||||
*/
|
||||
/** The base url of the application */
|
||||
readonly VITE_BASE_URL: string;
|
||||
/**
|
||||
* the title of the application
|
||||
*/
|
||||
/** The title of the application */
|
||||
readonly VITE_APP_TITLE: string;
|
||||
/**
|
||||
* the description of the application
|
||||
*/
|
||||
/** The description of the application */
|
||||
readonly VITE_APP_DESC: string;
|
||||
/**
|
||||
* the router history mode
|
||||
*/
|
||||
/** The router history mode */
|
||||
readonly VITE_ROUTER_HISTORY_MODE?: RouterHistoryMode;
|
||||
/**
|
||||
* the prefix of the iconify icon
|
||||
*/
|
||||
/** The prefix of the iconify icon */
|
||||
readonly VITE_ICON_PREFIX: 'icon';
|
||||
/**
|
||||
* the prefix of the local icon
|
||||
* @description this prefix is start with the icon prefix
|
||||
* The prefix of the local icon
|
||||
*
|
||||
* This prefix is start with the icon prefix
|
||||
*/
|
||||
readonly VITE_ICON_LOCAL_PREFIX: 'local-icon';
|
||||
/**
|
||||
* whether to enable the http proxy
|
||||
* @description only valid in the development environment
|
||||
* Whether to enable the http proxy
|
||||
*
|
||||
* Only valid in the development environment
|
||||
*/
|
||||
readonly VITE_HTTP_PROXY?: Common.YesOrNo;
|
||||
/**
|
||||
* the back service env
|
||||
*/
|
||||
/** The back service env */
|
||||
readonly VITE_SERVICE_ENV?: App.Service.EnvType;
|
||||
/**
|
||||
* the auth route mode
|
||||
* - static: the auth routes is generated in front-end
|
||||
* - dynamic: the auth routes is generated in back-end
|
||||
* The auth route mode
|
||||
*
|
||||
* - Static: the auth routes is generated in front-end
|
||||
* - Dynamic: the auth routes is generated in back-end
|
||||
*/
|
||||
readonly VITE_AUTH_ROUTE_MODE: 'static' | 'dynamic';
|
||||
/**
|
||||
* the home route key
|
||||
* @description it only has effect when the auth route mode is static, if the route mode is dynamic, the home route key is defined in the back-end
|
||||
* The home route key
|
||||
*
|
||||
* It only has effect when the auth route mode is static, if the route mode is dynamic, the home route key is
|
||||
* defined in the back-end
|
||||
*/
|
||||
readonly VITE_ROUTE_HOME: import('@elegant-router/types').LastLevelRouteKey;
|
||||
/**
|
||||
* default menu icon if menu icon is not set
|
||||
* @description iconify icon name
|
||||
* Default menu icon if menu icon is not set
|
||||
*
|
||||
* Iconify icon name
|
||||
*/
|
||||
readonly VITE_MENU_ICON: string;
|
||||
/**
|
||||
* whether to build with sourcemap
|
||||
*/
|
||||
/** Whether to build with sourcemap */
|
||||
readonly VITE_SOURCE_MAP?: Common.YesOrNo;
|
||||
/**
|
||||
* iconify api provider url
|
||||
* @description if the project is deployed in intranet, you can set the api provider url to the local iconify server
|
||||
* Iconify api provider url
|
||||
*
|
||||
* If the project is deployed in intranet, you can set the api provider url to the local iconify server
|
||||
*
|
||||
* @link https://docs.iconify.design/api/providers.html
|
||||
*/
|
||||
readonly VITE_ICONIFY_URL?: string;
|
||||
|
||||
24
src/typings/global.d.ts
vendored
24
src/typings/global.d.ts
vendored
@ -1,23 +1,13 @@
|
||||
interface Window {
|
||||
/**
|
||||
* NProgress instance
|
||||
*/
|
||||
/** NProgress instance */
|
||||
NProgress?: import('nprogress').NProgress;
|
||||
/**
|
||||
* loading bar instance
|
||||
*/
|
||||
/** Loading bar instance */
|
||||
$loadingBar?: import('naive-ui').LoadingBarProviderInst;
|
||||
/**
|
||||
* dialog instance
|
||||
*/
|
||||
/** Dialog instance */
|
||||
$dialog?: import('naive-ui').DialogProviderInst;
|
||||
/**
|
||||
* message instance
|
||||
*/
|
||||
/** Message instance */
|
||||
$message?: import('naive-ui').MessageProviderInst;
|
||||
/**
|
||||
* notification instance
|
||||
*/
|
||||
/** Notification instance */
|
||||
$notification?: import('naive-ui').NotificationProviderInst;
|
||||
}
|
||||
|
||||
@ -33,7 +23,5 @@ interface ImportMeta {
|
||||
readonly env: Env.ImportMeta;
|
||||
}
|
||||
|
||||
/**
|
||||
* build time of the project
|
||||
*/
|
||||
/** Build time of the project */
|
||||
declare const BUILD_TIME: string;
|
||||
|
||||
63
src/typings/router.d.ts
vendored
63
src/typings/router.d.ts
vendored
@ -3,64 +3,61 @@ import 'vue-router';
|
||||
declare module 'vue-router' {
|
||||
interface RouteMeta {
|
||||
/**
|
||||
* title of the route
|
||||
* @description it can be used in document title
|
||||
* Title of the route
|
||||
*
|
||||
* It can be used in document title
|
||||
*/
|
||||
title: string;
|
||||
/**
|
||||
* i18n key of the route
|
||||
* @description it's used in i18n, if it is set, the title will be ignored
|
||||
* I18n key of the route
|
||||
*
|
||||
* It's used in i18n, if it is set, the title will be ignored
|
||||
*/
|
||||
i18nKey?: App.I18n.I18nKey;
|
||||
/**
|
||||
* roles of the route
|
||||
* @description route can be accessed if the current user has at least one of the roles
|
||||
* Roles of the route
|
||||
*
|
||||
* Route can be accessed if the current user has at least one of the roles
|
||||
*/
|
||||
roles?: string[];
|
||||
/**
|
||||
* whether to cache the route
|
||||
*/
|
||||
/** Whether to cache the route */
|
||||
keepAlive?: boolean;
|
||||
/**
|
||||
* is constant route
|
||||
* @description does not need to login, and the route is defined in the front-end
|
||||
* Is constant route
|
||||
*
|
||||
* Does not need to login, and the route is defined in the front-end
|
||||
*/
|
||||
constant?: boolean;
|
||||
/**
|
||||
* iconify icon
|
||||
* @description it can be used in the menu or breadcrumb
|
||||
* Iconify icon
|
||||
*
|
||||
* It can be used in the menu or breadcrumb
|
||||
*/
|
||||
icon?: string;
|
||||
/**
|
||||
* local icon
|
||||
* @description in "src/assets/svg-icon", if it is set, the icon will be ignored
|
||||
* Local icon
|
||||
*
|
||||
* In "src/assets/svg-icon", if it is set, the icon will be ignored
|
||||
*/
|
||||
localIcon?: string;
|
||||
/**
|
||||
* router order
|
||||
*/
|
||||
/** Router order */
|
||||
order?: number;
|
||||
/**
|
||||
* the outer link of the route
|
||||
*/
|
||||
/** The outer link of the route */
|
||||
href?: string;
|
||||
/**
|
||||
* whether to hide the route in the menu
|
||||
*/
|
||||
/** Whether to hide the route in the menu */
|
||||
hideInMenu?: boolean;
|
||||
/**
|
||||
* the menu key will be activated when entering the route
|
||||
* @description the route is not in the menu
|
||||
* @example the route is "user_detail", if it is set to "user_list", the menu "user_list" will be activated
|
||||
* The menu key will be activated when entering the route
|
||||
*
|
||||
* The route is not in the menu
|
||||
*
|
||||
* @example
|
||||
* the route is "user_detail", if it is set to "user_list", the menu "user_list" will be activated
|
||||
*/
|
||||
activeMenu?: import('@elegant-router/types').LastLevelRouteKey;
|
||||
/**
|
||||
* by default, the same route path will use one tab, if set to true, it will use multiple tabs
|
||||
*/
|
||||
/** By default, the same route path will use one tab, if set to true, it will use multiple tabs */
|
||||
multiTab?: boolean;
|
||||
/**
|
||||
* if set, the route will be fixed in tabs, and the value is the order of fixed tabs
|
||||
*/
|
||||
/** If set, the route will be fixed in tabs, and the value is the order of fixed tabs */
|
||||
fixedIndexInTab?: number;
|
||||
}
|
||||
}
|
||||
|
||||
41
src/typings/storage.d.ts
vendored
41
src/typings/storage.d.ts
vendored
@ -1,11 +1,7 @@
|
||||
/**
|
||||
* the storage namespace
|
||||
*/
|
||||
/** The storage namespace */
|
||||
declare namespace StorageType {
|
||||
interface Session {
|
||||
/**
|
||||
* the theme color
|
||||
*/
|
||||
/** The theme color */
|
||||
themeColor: string;
|
||||
// /**
|
||||
// * the theme settings
|
||||
@ -14,38 +10,25 @@ declare namespace StorageType {
|
||||
}
|
||||
|
||||
interface Local {
|
||||
/**
|
||||
* the i18n language
|
||||
*/
|
||||
/** The i18n language */
|
||||
lang: App.I18n.LangType;
|
||||
/**
|
||||
* the token
|
||||
*/
|
||||
/** The token */
|
||||
token: string;
|
||||
/**
|
||||
* the refresh token
|
||||
*/
|
||||
/** The refresh token */
|
||||
refreshToken: string;
|
||||
/**
|
||||
* the user info
|
||||
*/
|
||||
/** The user info */
|
||||
userInfo: Api.Auth.UserInfo;
|
||||
/**
|
||||
* the theme color
|
||||
*/
|
||||
/** The theme color */
|
||||
themeColor: string;
|
||||
/**
|
||||
* the theme settings
|
||||
*/
|
||||
/** The theme settings */
|
||||
themeSettings: App.Theme.ThemeSetting;
|
||||
/**
|
||||
* the override theme flags
|
||||
* @description the value is the build time of the project
|
||||
* The override theme flags
|
||||
*
|
||||
* The value is the build time of the project
|
||||
*/
|
||||
overrideThemeFlag: string;
|
||||
/**
|
||||
* the global tabs
|
||||
*/
|
||||
/** The global tabs */
|
||||
globalTabs: App.Global.Tab[];
|
||||
}
|
||||
}
|
||||
|
||||
54
src/typings/union-key.d.ts
vendored
54
src/typings/union-key.d.ts
vendored
@ -1,53 +1,49 @@
|
||||
/**
|
||||
* the union key namespace
|
||||
*/
|
||||
/** The union key namespace */
|
||||
declare namespace UnionKey {
|
||||
/**
|
||||
* the login module
|
||||
* - pwd-login: password login
|
||||
* - code-login: phone code login
|
||||
* - register: register
|
||||
* - reset-pwd: reset password
|
||||
* - bind-wechat: bind wechat
|
||||
* The login module
|
||||
*
|
||||
* - Pwd-login: password login
|
||||
* - Code-login: phone code login
|
||||
* - Register: register
|
||||
* - Reset-pwd: reset password
|
||||
* - Bind-wechat: bind wechat
|
||||
*/
|
||||
type LoginModule = 'pwd-login' | 'code-login' | 'register' | 'reset-pwd' | 'bind-wechat';
|
||||
|
||||
/**
|
||||
* theme scheme
|
||||
*/
|
||||
/** Theme scheme */
|
||||
type ThemeScheme = 'light' | 'dark' | 'auto';
|
||||
|
||||
/**
|
||||
* the layout mode
|
||||
* - vertical: the vertical menu in left
|
||||
* - horizontal: the horizontal menu in top
|
||||
* - vertical-mix: two vertical mixed menus in left
|
||||
* - horizontal-mix: the vertical menu in left and horizontal menu in top
|
||||
* The layout mode
|
||||
*
|
||||
* - Vertical: the vertical menu in left
|
||||
* - Horizontal: the horizontal menu in top
|
||||
* - Vertical-mix: two vertical mixed menus in left
|
||||
* - Horizontal-mix: the vertical menu in left and horizontal menu in top
|
||||
*/
|
||||
type ThemeLayoutMode = 'vertical' | 'horizontal' | 'vertical-mix' | 'horizontal-mix';
|
||||
|
||||
/**
|
||||
* the scroll mode when content overflow
|
||||
* - wrapper the wrapper component's root element overflow
|
||||
* - content the content component overflow
|
||||
* The scroll mode when content overflow
|
||||
*
|
||||
* - Wrapper the wrapper component's root element overflow
|
||||
* - Content the content component overflow
|
||||
*/
|
||||
type ThemeScrollMode = import('@sa/materials').LayoutScrollMode;
|
||||
|
||||
/**
|
||||
* page animate mode
|
||||
*/
|
||||
/** Page animate mode */
|
||||
type ThemePageAnimateMode = 'fade' | 'fade-slide' | 'fade-bottom' | 'fade-scale' | 'zoom-fade' | 'zoom-out' | 'none';
|
||||
|
||||
/**
|
||||
* tab mode
|
||||
* - chrome: chrome style
|
||||
* - button: button style
|
||||
* Tab mode
|
||||
*
|
||||
* - Chrome: chrome style
|
||||
* - Button: button style
|
||||
*/
|
||||
type ThemeTabMode = import('@sa/materials').PageTabMode;
|
||||
|
||||
/**
|
||||
* unocss animate key
|
||||
*/
|
||||
/** Unocss animate key */
|
||||
type UnoCssAnimateKey =
|
||||
| 'pulse'
|
||||
| 'bounce'
|
||||
|
||||
@ -1,18 +1,20 @@
|
||||
/**
|
||||
* transform record to option
|
||||
* @param record
|
||||
* Transform record to option
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const record = {
|
||||
* key1: 'label1',
|
||||
* key2: 'label2'
|
||||
* };
|
||||
* const options = transformRecordToOption(record);
|
||||
* // [
|
||||
* // { value: 'key1', label: 'label1' },
|
||||
* // { value: 'key2', label: 'label2' }
|
||||
* // ]
|
||||
* ```
|
||||
* ```ts
|
||||
* const record = {
|
||||
* key1: 'label1',
|
||||
* key2: 'label2'
|
||||
* };
|
||||
* const options = transformRecordToOption(record);
|
||||
* // [
|
||||
* // { value: 'key1', label: 'label1' },
|
||||
* // { value: 'key2', label: 'label2' }
|
||||
* // ]
|
||||
* ```;
|
||||
*
|
||||
* @param record
|
||||
*/
|
||||
export function transformRecordToOption<T extends Record<string, string>>(record: T) {
|
||||
return Object.entries(record).map(([value, label]) => ({
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { createStorage, createLocalforage } from '@sa/utils';
|
||||
import { createLocalforage, createStorage } from '@sa/utils';
|
||||
|
||||
export const localStg = createStorage<StorageType.Local>('local');
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ import { reactive } from 'vue';
|
||||
import { $t } from '@/locales';
|
||||
import { loginModuleRecord } from '@/constants/app';
|
||||
import { useRouterPush } from '@/hooks/common/router';
|
||||
import { useNaiveForm, useFormRules } from '@/hooks/common/form';
|
||||
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
|
||||
import { useAuthStore } from '@/store/modules/auth';
|
||||
|
||||
defineOptions({
|
||||
@ -48,7 +48,7 @@ async function handleSubmit() {
|
||||
:placeholder="$t('page.login.common.passwordPlaceholder')"
|
||||
/>
|
||||
</NFormItem>
|
||||
<NSpace :vertical="true" :size="24">
|
||||
<NSpace vertical :size="24">
|
||||
<div class="flex-y-center justify-between">
|
||||
<NCheckbox>{{ $t('page.login.pwdLogin.rememberMe') }}</NCheckbox>
|
||||
<NButton quaternary>{{ $t('page.login.pwdLogin.forgetPassword') }}</NButton>
|
||||
|
||||
@ -13,9 +13,7 @@ import ResetPwd from './components/reset-pwd.vue';
|
||||
import BindWechat from './components/bind-wechat.vue';
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
* the login module
|
||||
*/
|
||||
/** The login module */
|
||||
module?: UnionKey.LoginModule;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user