fix: fix keepAlive parameter error (#4194)
* fix: mock server deployment error * chore: typopull/48/MERGE
							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'; | ||||||
|  |  | ||||||
|  | @ -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 || | ||||||
|     isSideMode.value && |     (props.headerToggleSidebarButton && | ||||||
|     !isSidebarMixedNav.value && |       isSideMode.value && | ||||||
|     !isMixedNav.value && |       !isSidebarMixedNav.value && | ||||||
|     !props.isMobile |       !isMixedNav.value && | ||||||
|  |       !props.isMobile) | ||||||
|   ); |   ); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
|  | @ -421,8 +425,12 @@ function handleClickMask() { | ||||||
|   sidebarCollapse.value = true; |   sidebarCollapse.value = true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function handleOpenMenu() { | function handleHeaderToggle() { | ||||||
|   sidebarCollapse.value = false; |   if (props.isMobile) { | ||||||
|  |     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
	
	 Vben
						Vben