mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-02-02 18:28:40 +08:00
fix: fix keepAlive parameter error (#4194)
* fix: mock server deployment error * chore: typo
This commit is contained in:
parent
01d60336a6
commit
1db87ff7ce
@ -4,17 +4,21 @@ import jwt from 'jsonwebtoken';
|
|||||||
|
|
||||||
import { UserInfo } from './mock-data';
|
import { UserInfo } from './mock-data';
|
||||||
|
|
||||||
|
// TODO: Replace with your own secret key
|
||||||
|
const ACCESS_TOKEN_SECRET = 'access_token_secret';
|
||||||
|
const REFRESH_TOKEN_SECRET = 'refresh_token_secret';
|
||||||
|
|
||||||
export interface UserPayload extends UserInfo {
|
export interface UserPayload extends UserInfo {
|
||||||
iat: number;
|
iat: number;
|
||||||
exp: number;
|
exp: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateAccessToken(user: UserInfo) {
|
export function generateAccessToken(user: UserInfo) {
|
||||||
return jwt.sign(user, process.env.ACCESS_TOKEN_SECRET, { expiresIn: '2h' });
|
return jwt.sign(user, ACCESS_TOKEN_SECRET, { expiresIn: '2h' });
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateRefreshToken(user: UserInfo) {
|
export function generateRefreshToken(user: UserInfo) {
|
||||||
return jwt.sign(user, process.env.REFRESH_TOKEN_SECRET, {
|
return jwt.sign(user, REFRESH_TOKEN_SECRET, {
|
||||||
expiresIn: '30d',
|
expiresIn: '30d',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -29,10 +33,7 @@ export function verifyAccessToken(
|
|||||||
|
|
||||||
const token = authHeader.split(' ')[1];
|
const token = authHeader.split(' ')[1];
|
||||||
try {
|
try {
|
||||||
const decoded = jwt.verify(
|
const decoded = jwt.verify(token, ACCESS_TOKEN_SECRET) as UserPayload;
|
||||||
token,
|
|
||||||
process.env.ACCESS_TOKEN_SECRET,
|
|
||||||
) as UserPayload;
|
|
||||||
|
|
||||||
const username = decoded.username;
|
const username = decoded.username;
|
||||||
const user = MOCK_USERS.find((item) => item.username === username);
|
const user = MOCK_USERS.find((item) => item.username === username);
|
||||||
@ -47,10 +48,7 @@ export function verifyRefreshToken(
|
|||||||
token: string,
|
token: string,
|
||||||
): null | Omit<UserInfo, 'password'> {
|
): null | Omit<UserInfo, 'password'> {
|
||||||
try {
|
try {
|
||||||
const decoded = jwt.verify(
|
const decoded = jwt.verify(token, REFRESH_TOKEN_SECRET) as UserPayload;
|
||||||
token,
|
|
||||||
process.env.REFRESH_TOKEN_SECRET,
|
|
||||||
) as UserPayload;
|
|
||||||
const username = decoded.username;
|
const username = decoded.username;
|
||||||
const user = MOCK_USERS.find((item) => item.username === username);
|
const user = MOCK_USERS.find((item) => item.username === username);
|
||||||
const { password: _pwd, ...userinfo } = user;
|
const { password: _pwd, ...userinfo } = user;
|
||||||
|
@ -28,7 +28,12 @@ apps/web-native
|
|||||||
|
|
||||||
## Mock 服务精简
|
## Mock 服务精简
|
||||||
|
|
||||||
如果你不需要`Mock`服务,你可以直接删除`apps/backend-mock`文件夹即可。
|
如果你不需要`Mock`服务,你可以直接删除`apps/backend-mock`文件夹。同时在你的应用下`.env.development`文件中删除`VITE_NITRO_MOCK`变量。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 是否开启 Nitro Mock服务,true 为开启,false 为关闭
|
||||||
|
VITE_NITRO_MOCK=false
|
||||||
|
```
|
||||||
|
|
||||||
## 安装依赖
|
## 安装依赖
|
||||||
|
|
||||||
@ -47,6 +52,11 @@ pnpm install
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"build:antd": "pnpm run build --filter=@vben/web-antd",
|
||||||
|
"build:docs": "pnpm run build --filter=@vben/docs",
|
||||||
|
"build:ele": "pnpm run build --filter=@vben/web-ele",
|
||||||
|
"build:naive": "pnpm run build --filter=@vben/web-naive",
|
||||||
|
"build:play": "pnpm run build --filter=@vben/playground",
|
||||||
"dev:antd": "pnpm -F @vben/web-antd run dev",
|
"dev:antd": "pnpm -F @vben/web-antd run dev",
|
||||||
"dev:docs": "pnpm -F @vben/docs run dev",
|
"dev:docs": "pnpm -F @vben/docs run dev",
|
||||||
"dev:ele": "pnpm -F @vben/web-ele run dev",
|
"dev:ele": "pnpm -F @vben/web-ele run dev",
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
/* Used for destructive actions such as <Button variant="destructive"> */
|
/* Used for destructive actions such as <Button variant="destructive"> */
|
||||||
|
|
||||||
--destructive: 0 78% 68%;
|
--destructive: 359.21 68.47% 56.47%;
|
||||||
--destructive-foreground: 0 0% 98%;
|
--destructive-foreground: 0 0% 98%;
|
||||||
|
|
||||||
/* Used for success actions such as <message> */
|
/* Used for success actions such as <message> */
|
||||||
@ -110,7 +110,7 @@
|
|||||||
--muted-foreground: 217.9 10.6% 64.9%;
|
--muted-foreground: 217.9 10.6% 64.9%;
|
||||||
--accent: 215 27.9% 16.9%;
|
--accent: 215 27.9% 16.9%;
|
||||||
--accent-foreground: 210 20% 98%;
|
--accent-foreground: 210 20% 98%;
|
||||||
--destructive: 0 62.8% 30.6%;
|
--destructive: 359.21 68.47% 56.47%;
|
||||||
--destructive-foreground: 210 20% 98%;
|
--destructive-foreground: 210 20% 98%;
|
||||||
--border: 215 27.9% 16.9%;
|
--border: 215 27.9% 16.9%;
|
||||||
--input: 215 27.9% 16.9%;
|
--input: 215 27.9% 16.9%;
|
||||||
@ -136,7 +136,7 @@
|
|||||||
--muted-foreground: 240 5% 64.9%;
|
--muted-foreground: 240 5% 64.9%;
|
||||||
--accent: 12 6.5% 15.1%;
|
--accent: 12 6.5% 15.1%;
|
||||||
--accent-foreground: 0 0% 98%;
|
--accent-foreground: 0 0% 98%;
|
||||||
--destructive: 0 62.8% 30.6%;
|
--destructive: 359.21 68.47% 56.47%;
|
||||||
--destructive-foreground: 0 85.7% 97.3%;
|
--destructive-foreground: 0 85.7% 97.3%;
|
||||||
--border: 240 3.7% 15.9%;
|
--border: 240 3.7% 15.9%;
|
||||||
--input: 240 3.7% 15.9%;
|
--input: 240 3.7% 15.9%;
|
||||||
@ -162,7 +162,7 @@
|
|||||||
--muted-foreground: 0 0% 63.9%;
|
--muted-foreground: 0 0% 63.9%;
|
||||||
--accent: 0 0% 14.9%;
|
--accent: 0 0% 14.9%;
|
||||||
--accent-foreground: 0 0% 98%;
|
--accent-foreground: 0 0% 98%;
|
||||||
--destructive: 0 62.8% 30.6%;
|
--destructive: 359.21 68.47% 56.47%;
|
||||||
--destructive-foreground: 0 0% 98%;
|
--destructive-foreground: 0 0% 98%;
|
||||||
--border: 0 0% 14.9%;
|
--border: 0 0% 14.9%;
|
||||||
--input: 0 0% 14.9%;
|
--input: 0 0% 14.9%;
|
||||||
@ -188,7 +188,7 @@
|
|||||||
--muted-foreground: 215 20.2% 65.1%;
|
--muted-foreground: 215 20.2% 65.1%;
|
||||||
--accent: 217.2 32.6% 17.5%;
|
--accent: 217.2 32.6% 17.5%;
|
||||||
--accent-foreground: 210 40% 98%;
|
--accent-foreground: 210 40% 98%;
|
||||||
--destructive: 0 62.8% 30.6%;
|
--destructive: 359.21 68.47% 56.47%;
|
||||||
--destructive-foreground: 210 40% 98%;
|
--destructive-foreground: 210 40% 98%;
|
||||||
--border: 217.2 32.6% 17.5%;
|
--border: 217.2 32.6% 17.5%;
|
||||||
--input: 217.2 32.6% 17.5%;
|
--input: 217.2 32.6% 17.5%;
|
||||||
@ -214,7 +214,7 @@
|
|||||||
--muted-foreground: 215 20.2% 65.1%;
|
--muted-foreground: 215 20.2% 65.1%;
|
||||||
--accent: 217.2 32.6% 17.5%;
|
--accent: 217.2 32.6% 17.5%;
|
||||||
--accent-foreground: 210 40% 98%;
|
--accent-foreground: 210 40% 98%;
|
||||||
--destructive: 0 62.8% 30.6%;
|
--destructive: 359.21 68.47% 56.47%;
|
||||||
--destructive-foreground: 210 40% 98%;
|
--destructive-foreground: 210 40% 98%;
|
||||||
--border: 217.2 32.6% 17.5%;
|
--border: 217.2 32.6% 17.5%;
|
||||||
--input: 217.2 32.6% 17.5%;
|
--input: 217.2 32.6% 17.5%;
|
||||||
@ -240,7 +240,7 @@
|
|||||||
--muted-foreground: 240 5% 64.9%;
|
--muted-foreground: 240 5% 64.9%;
|
||||||
--accent: 12 6.5% 15.1%;
|
--accent: 12 6.5% 15.1%;
|
||||||
--accent-foreground: 0 0% 98%;
|
--accent-foreground: 0 0% 98%;
|
||||||
--destructive: 0 62.8% 30.6%;
|
--destructive: 359.21 68.47% 56.47%;
|
||||||
--destructive-foreground: 0 85.7% 97.3%;
|
--destructive-foreground: 0 85.7% 97.3%;
|
||||||
--border: 240 3.7% 15.9%;
|
--border: 240 3.7% 15.9%;
|
||||||
--input: 240 3.7% 15.9%;
|
--input: 240 3.7% 15.9%;
|
||||||
@ -266,7 +266,7 @@
|
|||||||
--muted-foreground: 240 5% 64.9%;
|
--muted-foreground: 240 5% 64.9%;
|
||||||
--accent: 12 6.5% 15.1%;
|
--accent: 12 6.5% 15.1%;
|
||||||
--accent-foreground: 0 0% 98%;
|
--accent-foreground: 0 0% 98%;
|
||||||
--destructive: 0 62.8% 30.6%;
|
--destructive: 359.21 68.47% 56.47%;
|
||||||
--destructive-foreground: 0 85.7% 97.3%;
|
--destructive-foreground: 0 85.7% 97.3%;
|
||||||
--border: 240 3.7% 15.9%;
|
--border: 240 3.7% 15.9%;
|
||||||
--input: 240 3.7% 15.9%;
|
--input: 240 3.7% 15.9%;
|
||||||
@ -318,7 +318,7 @@
|
|||||||
--muted-foreground: 24 5.4% 63.9%;
|
--muted-foreground: 24 5.4% 63.9%;
|
||||||
--accent: 12 6.5% 15.1%;
|
--accent: 12 6.5% 15.1%;
|
||||||
--accent-foreground: 60 9.1% 97.8%;
|
--accent-foreground: 60 9.1% 97.8%;
|
||||||
--destructive: 0 62.8% 30.6%;
|
--destructive: 359.21 68.47% 56.47%;
|
||||||
--destructive-foreground: 60 9.1% 97.8%;
|
--destructive-foreground: 60 9.1% 97.8%;
|
||||||
--border: 12 6.5% 15.1%;
|
--border: 12 6.5% 15.1%;
|
||||||
--input: 12 6.5% 15.1%;
|
--input: 12 6.5% 15.1%;
|
||||||
@ -344,7 +344,7 @@
|
|||||||
--muted-foreground: 240 5% 64.9%;
|
--muted-foreground: 240 5% 64.9%;
|
||||||
--accent: 240 3.7% 15.9%;
|
--accent: 240 3.7% 15.9%;
|
||||||
--accent-foreground: 0 0% 98%;
|
--accent-foreground: 0 0% 98%;
|
||||||
--destructive: 0 62.8% 30.6%;
|
--destructive: 359.21 68.47% 56.47%;
|
||||||
--destructive-foreground: 0 0% 98%;
|
--destructive-foreground: 0 0% 98%;
|
||||||
--border: 240 3.7% 15.9%;
|
--border: 240 3.7% 15.9%;
|
||||||
--input: 240 3.7% 15.9%;
|
--input: 240 3.7% 15.9%;
|
||||||
@ -370,7 +370,7 @@
|
|||||||
--muted-foreground: 0 0% 63.9%;
|
--muted-foreground: 0 0% 63.9%;
|
||||||
--accent: 0 0% 14.9%;
|
--accent: 0 0% 14.9%;
|
||||||
--accent-foreground: 0 0% 98%;
|
--accent-foreground: 0 0% 98%;
|
||||||
--destructive: 0 62.8% 30.6%;
|
--destructive: 359.21 68.47% 56.47%;
|
||||||
--destructive-foreground: 0 0% 98%;
|
--destructive-foreground: 0 0% 98%;
|
||||||
--border: 0 0% 14.9%;
|
--border: 0 0% 14.9%;
|
||||||
--input: 0 0% 14.9%;
|
--input: 0 0% 14.9%;
|
||||||
@ -396,7 +396,7 @@
|
|||||||
--muted-foreground: 215 20.2% 65.1%;
|
--muted-foreground: 215 20.2% 65.1%;
|
||||||
--accent: 217.2 32.6% 17.5%;
|
--accent: 217.2 32.6% 17.5%;
|
||||||
--accent-foreground: 210 40% 98%;
|
--accent-foreground: 210 40% 98%;
|
||||||
--destructive: 0 62.8% 30.6%;
|
--destructive: 359.21 68.47% 56.47%;
|
||||||
--destructive-foreground: 210 40% 98%;
|
--destructive-foreground: 210 40% 98%;
|
||||||
--border: 217.2 32.6% 17.5%;
|
--border: 217.2 32.6% 17.5%;
|
||||||
--input: 217.2 32.6% 17.5%;
|
--input: 217.2 32.6% 17.5%;
|
||||||
@ -422,7 +422,7 @@
|
|||||||
--muted-foreground: 217.9 10.6% 64.9%;
|
--muted-foreground: 217.9 10.6% 64.9%;
|
||||||
--accent: 215 27.9% 16.9%;
|
--accent: 215 27.9% 16.9%;
|
||||||
--accent-foreground: 210 20% 98%;
|
--accent-foreground: 210 20% 98%;
|
||||||
--destructive: 0 62.8% 30.6%;
|
--destructive: 359.21 68.47% 56.47%;
|
||||||
--destructive-foreground: 210 20% 98%;
|
--destructive-foreground: 210 20% 98%;
|
||||||
--border: 215 27.9% 16.9%;
|
--border: 215 27.9% 16.9%;
|
||||||
--input: 215 27.9% 16.9%;
|
--input: 215 27.9% 16.9%;
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
/* Used for destructive actions such as <Button variant="destructive"> */
|
/* Used for destructive actions such as <Button variant="destructive"> */
|
||||||
|
|
||||||
--destructive: 0 78% 68%;
|
--destructive: 359.33 100% 65.1%;
|
||||||
--destructive-foreground: 0 0% 98%;
|
--destructive-foreground: 0 0% 98%;
|
||||||
|
|
||||||
/* Used for success actions such as <message> */
|
/* Used for success actions such as <message> */
|
||||||
|
@ -5,6 +5,7 @@ export * from './inference';
|
|||||||
export * from './letter';
|
export * from './letter';
|
||||||
export * from './merge';
|
export * from './merge';
|
||||||
export * from './nprogress';
|
export * from './nprogress';
|
||||||
|
export * from './to';
|
||||||
export * from './tree';
|
export * from './tree';
|
||||||
export * from './unique';
|
export * from './unique';
|
||||||
export * from './update-css-variables';
|
export * from './update-css-variables';
|
||||||
|
21
packages/@core/base/shared/src/utils/to.ts
Normal file
21
packages/@core/base/shared/src/utils/to.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* @param { Readonly<Promise> } promise
|
||||||
|
* @param {object=} errorExt - Additional Information you can pass to the err object
|
||||||
|
* @return { Promise }
|
||||||
|
*/
|
||||||
|
export async function to<T, U = Error>(
|
||||||
|
promise: Readonly<Promise<T>>,
|
||||||
|
errorExt?: object,
|
||||||
|
): Promise<[null, T] | [U, undefined]> {
|
||||||
|
try {
|
||||||
|
const data = await promise;
|
||||||
|
const result: [null, T] = [null, data];
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
if (errorExt) {
|
||||||
|
const parsedError = Object.assign({}, error, errorExt);
|
||||||
|
return [parsedError as U, undefined];
|
||||||
|
}
|
||||||
|
return [error as U, undefined];
|
||||||
|
}
|
||||||
|
}
|
@ -2,9 +2,6 @@
|
|||||||
import type { CSSProperties } from 'vue';
|
import type { CSSProperties } from 'vue';
|
||||||
import { computed, useSlots } from 'vue';
|
import { computed, useSlots } from 'vue';
|
||||||
|
|
||||||
import { Menu } from '@vben-core/icons';
|
|
||||||
import { VbenIconButton } from '@vben-core/shadcn-ui';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
/**
|
/**
|
||||||
* 横屏
|
* 横屏
|
||||||
@ -14,11 +11,6 @@ interface Props {
|
|||||||
* 高度
|
* 高度
|
||||||
*/
|
*/
|
||||||
height: number;
|
height: number;
|
||||||
/**
|
|
||||||
* 是否混合导航
|
|
||||||
* @default false
|
|
||||||
*/
|
|
||||||
isMixedNav: boolean;
|
|
||||||
/**
|
/**
|
||||||
* 是否移动端
|
* 是否移动端
|
||||||
*/
|
*/
|
||||||
@ -27,11 +19,6 @@ interface Props {
|
|||||||
* 是否显示
|
* 是否显示
|
||||||
*/
|
*/
|
||||||
show: boolean;
|
show: boolean;
|
||||||
/**
|
|
||||||
* 是否显示关闭菜单按钮
|
|
||||||
*/
|
|
||||||
showToggleBtn: boolean;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 侧边菜单宽度
|
* 侧边菜单宽度
|
||||||
*/
|
*/
|
||||||
@ -52,8 +39,6 @@ interface Props {
|
|||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {});
|
const props = withDefaults(defineProps<Props>(), {});
|
||||||
|
|
||||||
const emit = defineEmits<{ openMenu: []; toggleSidebar: [] }>();
|
|
||||||
|
|
||||||
const slots = useSlots();
|
const slots = useSlots();
|
||||||
|
|
||||||
const style = computed((): CSSProperties => {
|
const style = computed((): CSSProperties => {
|
||||||
@ -72,10 +57,6 @@ const logoStyle = computed((): CSSProperties => {
|
|||||||
minWidth: `${props.isMobile ? 40 : props.sidebarWidth}px`,
|
minWidth: `${props.isMobile ? 40 : props.sidebarWidth}px`,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
function handleToggleMenu() {
|
|
||||||
props.isMobile ? emit('openMenu') : emit('toggleSidebar');
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -87,13 +68,9 @@ function handleToggleMenu() {
|
|||||||
<div v-if="slots.logo" :style="logoStyle">
|
<div v-if="slots.logo" :style="logoStyle">
|
||||||
<slot name="logo"></slot>
|
<slot name="logo"></slot>
|
||||||
</div>
|
</div>
|
||||||
<VbenIconButton
|
|
||||||
v-if="showToggleBtn || isMobile"
|
<slot name="toggle-button"> </slot>
|
||||||
class="my-0 ml-2 mr-1 rounded-md"
|
|
||||||
@click="handleToggleMenu"
|
|
||||||
>
|
|
||||||
<Menu class="size-4" />
|
|
||||||
</VbenIconButton>
|
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</header>
|
</header>
|
||||||
</template>
|
</template>
|
||||||
|
@ -4,6 +4,9 @@ import type { VbenLayoutProps } from './vben-layout';
|
|||||||
import type { CSSProperties } from 'vue';
|
import type { CSSProperties } from 'vue';
|
||||||
import { computed, ref, watch } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
|
|
||||||
|
import { Menu } from '@vben-core/icons';
|
||||||
|
import { VbenIconButton } from '@vben-core/shadcn-ui';
|
||||||
|
|
||||||
import { useMouse, useScroll, useThrottleFn } from '@vueuse/core';
|
import { useMouse, useScroll, useThrottleFn } from '@vueuse/core';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -330,11 +333,12 @@ const maskStyle = computed((): CSSProperties => {
|
|||||||
|
|
||||||
const showHeaderToggleButton = computed(() => {
|
const showHeaderToggleButton = computed(() => {
|
||||||
return (
|
return (
|
||||||
props.headerToggleSidebarButton &&
|
props.isMobile ||
|
||||||
|
(props.headerToggleSidebarButton &&
|
||||||
isSideMode.value &&
|
isSideMode.value &&
|
||||||
!isSidebarMixedNav.value &&
|
!isSidebarMixedNav.value &&
|
||||||
!isMixedNav.value &&
|
!isMixedNav.value &&
|
||||||
!props.isMobile
|
!props.isMobile)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -421,8 +425,12 @@ function handleClickMask() {
|
|||||||
sidebarCollapse.value = true;
|
sidebarCollapse.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleOpenMenu() {
|
function handleHeaderToggle() {
|
||||||
|
if (props.isMobile) {
|
||||||
sidebarCollapse.value = false;
|
sidebarCollapse.value = false;
|
||||||
|
} else {
|
||||||
|
emit('toggleSidebar');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -473,27 +481,36 @@ function handleOpenMenu() {
|
|||||||
class="flex flex-1 flex-col overflow-hidden transition-all duration-300 ease-in"
|
class="flex flex-1 flex-col overflow-hidden transition-all duration-300 ease-in"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
:class="{
|
||||||
|
'shadow-[0_16px_24px_hsl(var(--background))]': scrollY > 20,
|
||||||
|
}"
|
||||||
:style="headerWrapperStyle"
|
:style="headerWrapperStyle"
|
||||||
class="overflow-hidden shadow-[0_16px_24px_hsl(var(--background))] transition-all duration-200"
|
class="overflow-hidden transition-all duration-200"
|
||||||
>
|
>
|
||||||
<LayoutHeader
|
<LayoutHeader
|
||||||
v-if="headerVisible"
|
v-if="headerVisible"
|
||||||
:full-width="!isSideMode"
|
:full-width="!isSideMode"
|
||||||
:height="headerHeight"
|
:height="headerHeight"
|
||||||
:is-mixed-nav="isMixedNav"
|
|
||||||
:is-mobile="isMobile"
|
:is-mobile="isMobile"
|
||||||
:show="!isFullContent && !headerHidden"
|
:show="!isFullContent && !headerHidden"
|
||||||
:show-toggle-btn="showHeaderToggleButton"
|
|
||||||
:sidebar-width="sidebarWidth"
|
:sidebar-width="sidebarWidth"
|
||||||
:theme="headerTheme"
|
:theme="headerTheme"
|
||||||
:width="mainStyle.width"
|
:width="mainStyle.width"
|
||||||
:z-index="headerZIndex"
|
:z-index="headerZIndex"
|
||||||
@open-menu="handleOpenMenu"
|
|
||||||
@toggle-sidebar="() => emit('toggleSidebar')"
|
|
||||||
>
|
>
|
||||||
<template v-if="showHeaderLogo" #logo>
|
<template v-if="showHeaderLogo" #logo>
|
||||||
<slot name="logo"></slot>
|
<slot name="logo"></slot>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template #toggle-button>
|
||||||
|
<VbenIconButton
|
||||||
|
v-if="showHeaderToggleButton"
|
||||||
|
class="my-0 ml-2 mr-1 rounded-md"
|
||||||
|
@click="handleHeaderToggle"
|
||||||
|
>
|
||||||
|
<Menu class="size-4" />
|
||||||
|
</VbenIconButton>
|
||||||
|
</template>
|
||||||
<slot name="header"></slot>
|
<slot name="header"></slot>
|
||||||
</LayoutHeader>
|
</LayoutHeader>
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { MenuItemProps, MenuItemRegistered } from '../interface';
|
import type { MenuItemProps, MenuItemRegistered } from '../types';
|
||||||
|
|
||||||
import { computed, onBeforeUnmount, onMounted, reactive, useSlots } from 'vue';
|
import { computed, onBeforeUnmount, onMounted, reactive, useSlots } from 'vue';
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import type {
|
|||||||
MenuItemRegistered,
|
MenuItemRegistered,
|
||||||
MenuProps,
|
MenuProps,
|
||||||
MenuProvider,
|
MenuProvider,
|
||||||
} from '../interface';
|
} from '../types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
computed,
|
computed,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { MenuItemProps } from '../interface';
|
import type { MenuItemProps } from '../types';
|
||||||
|
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { HoverCardContentProps } from '@vben-core/shadcn-ui';
|
import type { HoverCardContentProps } from '@vben-core/shadcn-ui';
|
||||||
|
|
||||||
import type {
|
import type { MenuItemRegistered, MenuProvider, SubMenuProps } from '../types';
|
||||||
MenuItemRegistered,
|
|
||||||
MenuProvider,
|
|
||||||
SubMenuProps,
|
|
||||||
} from '../interface';
|
|
||||||
|
|
||||||
import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue';
|
import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue';
|
||||||
|
|
||||||
@ -74,7 +70,6 @@ const contentProps = computed((): HoverCardContentProps => {
|
|||||||
collisionPadding: { top: 20 },
|
collisionPadding: { top: 20 },
|
||||||
side,
|
side,
|
||||||
sideOffset: isHorizontal ? 5 : 10,
|
sideOffset: isHorizontal ? 5 : 10,
|
||||||
// sideOffset: 10,
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -216,7 +211,7 @@ onBeforeUnmount(() => {
|
|||||||
]"
|
]"
|
||||||
:content-props="contentProps"
|
:content-props="contentProps"
|
||||||
:open="true"
|
:open="true"
|
||||||
:open-delay="30"
|
:open-delay="0"
|
||||||
>
|
>
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
<SubMenuContent
|
<SubMenuContent
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { MenuProvider, SubMenuProvider } from '../interface';
|
import type { MenuProvider, SubMenuProvider } from '../types';
|
||||||
|
|
||||||
import { getCurrentInstance, inject, provide } from 'vue';
|
import { getCurrentInstance, inject, provide } from 'vue';
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { SubMenuProvider } from '../interface';
|
import type { SubMenuProvider } from '../types';
|
||||||
|
|
||||||
import { computed, getCurrentInstance } from 'vue';
|
import { computed, getCurrentInstance } from 'vue';
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
export * from './components/normal-menu';
|
export * from './components/normal-menu';
|
||||||
export type * from './interface';
|
|
||||||
export { default as Menu } from './menu.vue';
|
export { default as Menu } from './menu.vue';
|
||||||
|
export type * from './types';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { MenuRecordRaw } from '@vben-core/typings';
|
import type { MenuRecordRaw } from '@vben-core/typings';
|
||||||
|
|
||||||
import type { MenuProps } from './interface';
|
import type { MenuProps } from './types';
|
||||||
|
|
||||||
import { useForwardProps } from '@vben-core/composables';
|
import { useForwardProps } from '@vben-core/composables';
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ const tabsView = computed((): TabConfig[] => {
|
|||||||
/>
|
/>
|
||||||
<Pin
|
<Pin
|
||||||
v-show="tab.affixTab && tabsView.length > 1 && tab.closable"
|
v-show="tab.affixTab && tabsView.length > 1 && tab.closable"
|
||||||
class="hover:text-accent-foreground text-accent-foreground/80 group-[.is-active]:text-accent-foreground mt-[2px] size-3.5 cursor-pointer rounded-full transition-all"
|
class="hover:text-accent-foreground text-accent-foreground/80 group-[.is-active]:text-accent-foreground mt-[1px] size-3.5 cursor-pointer rounded-full transition-all"
|
||||||
@click.stop="() => emit('unpin', tab)"
|
@click.stop="() => emit('unpin', tab)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -150,18 +150,6 @@ const tabsView = computed((): TabConfig[] => {
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.tabs-chrome {
|
.tabs-chrome {
|
||||||
/* .dragging { */
|
|
||||||
|
|
||||||
/* .tabs-chrome__item-main {
|
|
||||||
@apply pr-0;
|
|
||||||
} */
|
|
||||||
|
|
||||||
/* .tabs-chrome__extra {
|
|
||||||
@apply hidden;
|
|
||||||
} */
|
|
||||||
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
&__item:not(.dragging) {
|
&__item:not(.dragging) {
|
||||||
@apply cursor-pointer;
|
@apply cursor-pointer;
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ const tabsView = computed((): TabConfig[] => {
|
|||||||
/>
|
/>
|
||||||
<Pin
|
<Pin
|
||||||
v-show="tab.affixTab && tabsView.length > 1 && tab.closable"
|
v-show="tab.affixTab && tabsView.length > 1 && tab.closable"
|
||||||
class="hover:bg-accent hover:stroke-accent-foreground group-[.is-active]:text-primary dark:group-[.is-active]:text-accent-foreground mt-[2px] size-3.5 cursor-pointer rounded-full transition-all"
|
class="hover:bg-accent hover:stroke-accent-foreground group-[.is-active]:text-primary dark:group-[.is-active]:text-accent-foreground mt-[1px] size-3.5 cursor-pointer rounded-full transition-all"
|
||||||
@click.stop="() => emit('unpin', tab)"
|
@click.stop="() => emit('unpin', tab)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -18,6 +18,7 @@ export function useAntdDesignTokens() {
|
|||||||
colorBgLayout: '',
|
colorBgLayout: '',
|
||||||
colorBgMask: '',
|
colorBgMask: '',
|
||||||
colorBorder: '',
|
colorBorder: '',
|
||||||
|
colorBorderSecondary: '',
|
||||||
colorError: '',
|
colorError: '',
|
||||||
colorInfo: '',
|
colorInfo: '',
|
||||||
colorPrimary: '',
|
colorPrimary: '',
|
||||||
@ -48,7 +49,8 @@ export function useAntdDesignTokens() {
|
|||||||
|
|
||||||
getCssVariableValue('--primary-foreground');
|
getCssVariableValue('--primary-foreground');
|
||||||
|
|
||||||
tokens.colorBorder = getCssVariableValue('--border');
|
tokens.colorBorderSecondary = tokens.colorBorder =
|
||||||
|
getCssVariableValue('--border');
|
||||||
|
|
||||||
tokens.colorBgElevated = getCssVariableValue('--popover');
|
tokens.colorBgElevated = getCssVariableValue('--popover');
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ export const useTabbarStore = defineStore('core-tabbar', {
|
|||||||
return !paths.includes(getTabPath(item));
|
return !paths.includes(getTabPath(item));
|
||||||
});
|
});
|
||||||
|
|
||||||
this.updateCacheTab();
|
this.updateCacheTabs();
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* @zh_CN 关闭标签页
|
* @zh_CN 关闭标签页
|
||||||
@ -141,7 +141,7 @@ export const useTabbarStore = defineStore('core-tabbar', {
|
|||||||
|
|
||||||
this.tabs.splice(tabIndex, 1, mergedTab);
|
this.tabs.splice(tabIndex, 1, mergedTab);
|
||||||
}
|
}
|
||||||
this.updateCacheTab();
|
this.updateCacheTabs();
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* @zh_CN 关闭所有标签页
|
* @zh_CN 关闭所有标签页
|
||||||
@ -150,7 +150,7 @@ export const useTabbarStore = defineStore('core-tabbar', {
|
|||||||
const newTabs = this.tabs.filter((tab) => isAffixTab(tab));
|
const newTabs = this.tabs.filter((tab) => isAffixTab(tab));
|
||||||
this.tabs = newTabs.length > 0 ? newTabs : [...this.tabs].splice(0, 1);
|
this.tabs = newTabs.length > 0 ? newTabs : [...this.tabs].splice(0, 1);
|
||||||
await this._goToDefaultTab(router);
|
await this._goToDefaultTab(router);
|
||||||
this.updateCacheTab();
|
this.updateCacheTabs();
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* @zh_CN 关闭左侧标签页
|
* @zh_CN 关闭左侧标签页
|
||||||
@ -230,7 +230,7 @@ export const useTabbarStore = defineStore('core-tabbar', {
|
|||||||
// 关闭不是激活选项卡
|
// 关闭不是激活选项卡
|
||||||
if (getTabPath(currentRoute.value) !== getTabPath(tab)) {
|
if (getTabPath(currentRoute.value) !== getTabPath(tab)) {
|
||||||
this._close(tab);
|
this._close(tab);
|
||||||
this.updateCacheTab();
|
this.updateCacheTabs();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const index = this.getTabs.findIndex(
|
const index = this.getTabs.findIndex(
|
||||||
@ -339,7 +339,7 @@ export const useTabbarStore = defineStore('core-tabbar', {
|
|||||||
);
|
);
|
||||||
if (findTab) {
|
if (findTab) {
|
||||||
findTab.meta.newTabTitle = undefined;
|
findTab.meta.newTabTitle = undefined;
|
||||||
await this.updateCacheTab();
|
await this.updateCacheTabs();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -367,7 +367,7 @@ export const useTabbarStore = defineStore('core-tabbar', {
|
|||||||
if (findTab) {
|
if (findTab) {
|
||||||
findTab.meta.newTabTitle = title;
|
findTab.meta.newTabTitle = title;
|
||||||
|
|
||||||
await this.updateCacheTab();
|
await this.updateCacheTabs();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -417,7 +417,7 @@ export const useTabbarStore = defineStore('core-tabbar', {
|
|||||||
/**
|
/**
|
||||||
* 根据当前打开的选项卡更新缓存
|
* 根据当前打开的选项卡更新缓存
|
||||||
*/
|
*/
|
||||||
async updateCacheTab() {
|
async updateCacheTabs() {
|
||||||
const cacheMap = new Set<string>();
|
const cacheMap = new Set<string>();
|
||||||
|
|
||||||
for (const tab of this.tabs) {
|
for (const tab of this.tabs) {
|
||||||
@ -426,7 +426,7 @@ export const useTabbarStore = defineStore('core-tabbar', {
|
|||||||
if (!keepAlive) {
|
if (!keepAlive) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
tab.matched.forEach((t, i) => {
|
(tab.matched || []).forEach((t, i) => {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
cacheMap.add(t.name as string);
|
cacheMap.add(t.name as string);
|
||||||
}
|
}
|
||||||
|
@ -6,3 +6,8 @@
|
|||||||
overscroll-behavior: none;
|
overscroll-behavior: none;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-message-notice-content,
|
||||||
|
.ant-notification-notice {
|
||||||
|
@apply dark:border-border/60 dark:border;
|
||||||
|
}
|
||||||
|
@ -2,4 +2,4 @@
|
|||||||
VITE_APP_TITLE=Vben Admin
|
VITE_APP_TITLE=Vben Admin
|
||||||
|
|
||||||
# 应用命名空间,用于缓存、store等功能的前缀,确保隔离
|
# 应用命名空间,用于缓存、store等功能的前缀,确保隔离
|
||||||
VITE_APP_NAMESPACE=vben-web-antd
|
VITE_APP_NAMESPACE=vben-web-play
|
||||||
|
Loading…
Reference in New Issue
Block a user