1
0
Эх сурвалжийг харах

fix: fix keepAlive parameter error (#4194)

* fix: mock server deployment error

* chore: typo
Vben 7 сар өмнө
parent
commit
1db87ff7ce

+ 8 - 10
apps/backend-mock/utils/jwt-utils.ts

@@ -4,17 +4,21 @@ import jwt from 'jsonwebtoken';
 
 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 {
   iat: number;
   exp: number;
 }
 
 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) {
-  return jwt.sign(user, process.env.REFRESH_TOKEN_SECRET, {
+  return jwt.sign(user, REFRESH_TOKEN_SECRET, {
     expiresIn: '30d',
   });
 }
@@ -29,10 +33,7 @@ export function verifyAccessToken(
 
   const token = authHeader.split(' ')[1];
   try {
-    const decoded = jwt.verify(
-      token,
-      process.env.ACCESS_TOKEN_SECRET,
-    ) as UserPayload;
+    const decoded = jwt.verify(token, ACCESS_TOKEN_SECRET) as UserPayload;
 
     const username = decoded.username;
     const user = MOCK_USERS.find((item) => item.username === username);
@@ -47,10 +48,7 @@ export function verifyRefreshToken(
   token: string,
 ): null | Omit<UserInfo, 'password'> {
   try {
-    const decoded = jwt.verify(
-      token,
-      process.env.REFRESH_TOKEN_SECRET,
-    ) as UserPayload;
+    const decoded = jwt.verify(token, REFRESH_TOKEN_SECRET) as UserPayload;
     const username = decoded.username;
     const user = MOCK_USERS.find((item) => item.username === username);
     const { password: _pwd, ...userinfo } = user;

+ 11 - 1
docs/src/guide/introduction/thin.md

@@ -28,7 +28,12 @@ apps/web-native
 
 ## 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
 {
   "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:docs": "pnpm -F @vben/docs run dev",
     "dev:ele": "pnpm -F @vben/web-ele run dev",

+ 13 - 13
packages/@core/base/design/src/design-tokens/dark/index.css

@@ -34,7 +34,7 @@
 
   /* 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%;
 
   /* Used for success actions such as <message> */
@@ -110,7 +110,7 @@
   --muted-foreground: 217.9 10.6% 64.9%;
   --accent: 215 27.9% 16.9%;
   --accent-foreground: 210 20% 98%;
-  --destructive: 0 62.8% 30.6%;
+  --destructive: 359.21 68.47% 56.47%;
   --destructive-foreground: 210 20% 98%;
   --border: 215 27.9% 16.9%;
   --input: 215 27.9% 16.9%;
@@ -136,7 +136,7 @@
   --muted-foreground: 240 5% 64.9%;
   --accent: 12 6.5% 15.1%;
   --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%;
   --border: 240 3.7% 15.9%;
   --input: 240 3.7% 15.9%;
@@ -162,7 +162,7 @@
   --muted-foreground: 0 0% 63.9%;
   --accent: 0 0% 14.9%;
   --accent-foreground: 0 0% 98%;
-  --destructive: 0 62.8% 30.6%;
+  --destructive: 359.21 68.47% 56.47%;
   --destructive-foreground: 0 0% 98%;
   --border: 0 0% 14.9%;
   --input: 0 0% 14.9%;
@@ -188,7 +188,7 @@
   --muted-foreground: 215 20.2% 65.1%;
   --accent: 217.2 32.6% 17.5%;
   --accent-foreground: 210 40% 98%;
-  --destructive: 0 62.8% 30.6%;
+  --destructive: 359.21 68.47% 56.47%;
   --destructive-foreground: 210 40% 98%;
   --border: 217.2 32.6% 17.5%;
   --input: 217.2 32.6% 17.5%;
@@ -214,7 +214,7 @@
   --muted-foreground: 215 20.2% 65.1%;
   --accent: 217.2 32.6% 17.5%;
   --accent-foreground: 210 40% 98%;
-  --destructive: 0 62.8% 30.6%;
+  --destructive: 359.21 68.47% 56.47%;
   --destructive-foreground: 210 40% 98%;
   --border: 217.2 32.6% 17.5%;
   --input: 217.2 32.6% 17.5%;
@@ -240,7 +240,7 @@
   --muted-foreground: 240 5% 64.9%;
   --accent: 12 6.5% 15.1%;
   --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%;
   --border: 240 3.7% 15.9%;
   --input: 240 3.7% 15.9%;
@@ -266,7 +266,7 @@
   --muted-foreground: 240 5% 64.9%;
   --accent: 12 6.5% 15.1%;
   --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%;
   --border: 240 3.7% 15.9%;
   --input: 240 3.7% 15.9%;
@@ -318,7 +318,7 @@
   --muted-foreground: 24 5.4% 63.9%;
   --accent: 12 6.5% 15.1%;
   --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%;
   --border: 12 6.5% 15.1%;
   --input: 12 6.5% 15.1%;
@@ -344,7 +344,7 @@
   --muted-foreground: 240 5% 64.9%;
   --accent: 240 3.7% 15.9%;
   --accent-foreground: 0 0% 98%;
-  --destructive: 0 62.8% 30.6%;
+  --destructive: 359.21 68.47% 56.47%;
   --destructive-foreground: 0 0% 98%;
   --border: 240 3.7% 15.9%;
   --input: 240 3.7% 15.9%;
@@ -370,7 +370,7 @@
   --muted-foreground: 0 0% 63.9%;
   --accent: 0 0% 14.9%;
   --accent-foreground: 0 0% 98%;
-  --destructive: 0 62.8% 30.6%;
+  --destructive: 359.21 68.47% 56.47%;
   --destructive-foreground: 0 0% 98%;
   --border: 0 0% 14.9%;
   --input: 0 0% 14.9%;
@@ -396,7 +396,7 @@
   --muted-foreground: 215 20.2% 65.1%;
   --accent: 217.2 32.6% 17.5%;
   --accent-foreground: 210 40% 98%;
-  --destructive: 0 62.8% 30.6%;
+  --destructive: 359.21 68.47% 56.47%;
   --destructive-foreground: 210 40% 98%;
   --border: 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%;
   --accent: 215 27.9% 16.9%;
   --accent-foreground: 210 20% 98%;
-  --destructive: 0 62.8% 30.6%;
+  --destructive: 359.21 68.47% 56.47%;
   --destructive-foreground: 210 20% 98%;
   --border: 215 27.9% 16.9%;
   --input: 215 27.9% 16.9%;

+ 1 - 1
packages/@core/base/design/src/design-tokens/default/index.css

@@ -33,7 +33,7 @@
 
   /* Used for destructive actions such as <Button variant="destructive"> */
 
-  --destructive: 0 78% 68%;
+  --destructive: 359.33 100% 65.1%;
   --destructive-foreground: 0 0% 98%;
 
   /* Used for success actions such as <message> */

+ 1 - 0
packages/@core/base/shared/src/utils/index.ts

@@ -5,6 +5,7 @@ export * from './inference';
 export * from './letter';
 export * from './merge';
 export * from './nprogress';
+export * from './to';
 export * from './tree';
 export * from './unique';
 export * from './update-css-variables';

+ 21 - 0
packages/@core/base/shared/src/utils/to.ts

@@ -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];
+  }
+}

+ 3 - 26
packages/@core/ui-kit/layout-ui/src/components/layout-header.vue

@@ -2,9 +2,6 @@
 import type { CSSProperties } from 'vue';
 import { computed, useSlots } from 'vue';
 
-import { Menu } from '@vben-core/icons';
-import { VbenIconButton } from '@vben-core/shadcn-ui';
-
 interface Props {
   /**
    * 横屏
@@ -14,11 +11,6 @@ interface Props {
    * 高度
    */
   height: number;
-  /**
-   * 是否混合导航
-   * @default false
-   */
-  isMixedNav: boolean;
   /**
    * 是否移动端
    */
@@ -27,11 +19,6 @@ interface Props {
    * 是否显示
    */
   show: boolean;
-  /**
-   * 是否显示关闭菜单按钮
-   */
-  showToggleBtn: boolean;
-
   /**
    * 侧边菜单宽度
    */
@@ -52,8 +39,6 @@ interface Props {
 
 const props = withDefaults(defineProps<Props>(), {});
 
-const emit = defineEmits<{ openMenu: []; toggleSidebar: [] }>();
-
 const slots = useSlots();
 
 const style = computed((): CSSProperties => {
@@ -72,10 +57,6 @@ const logoStyle = computed((): CSSProperties => {
     minWidth: `${props.isMobile ? 40 : props.sidebarWidth}px`,
   };
 });
-
-function handleToggleMenu() {
-  props.isMobile ? emit('openMenu') : emit('toggleSidebar');
-}
 </script>
 
 <template>
@@ -87,13 +68,9 @@ function handleToggleMenu() {
     <div v-if="slots.logo" :style="logoStyle">
       <slot name="logo"></slot>
     </div>
-    <VbenIconButton
-      v-if="showToggleBtn || isMobile"
-      class="my-0 ml-2 mr-1 rounded-md"
-      @click="handleToggleMenu"
-    >
-      <Menu class="size-4" />
-    </VbenIconButton>
+
+    <slot name="toggle-button"> </slot>
+
     <slot></slot>
   </header>
 </template>

+ 29 - 12
packages/@core/ui-kit/layout-ui/src/vben-layout.vue

@@ -4,6 +4,9 @@ import type { VbenLayoutProps } from './vben-layout';
 import type { CSSProperties } 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 {
@@ -330,11 +333,12 @@ const maskStyle = computed((): CSSProperties => {
 
 const showHeaderToggleButton = computed(() => {
   return (
-    props.headerToggleSidebarButton &&
-    isSideMode.value &&
-    !isSidebarMixedNav.value &&
-    !isMixedNav.value &&
-    !props.isMobile
+    props.isMobile ||
+    (props.headerToggleSidebarButton &&
+      isSideMode.value &&
+      !isSidebarMixedNav.value &&
+      !isMixedNav.value &&
+      !props.isMobile)
   );
 });
 
@@ -421,8 +425,12 @@ function handleClickMask() {
   sidebarCollapse.value = true;
 }
 
-function handleOpenMenu() {
-  sidebarCollapse.value = false;
+function handleHeaderToggle() {
+  if (props.isMobile) {
+    sidebarCollapse.value = false;
+  } else {
+    emit('toggleSidebar');
+  }
 }
 </script>
 
@@ -473,27 +481,36 @@ function handleOpenMenu() {
       class="flex flex-1 flex-col overflow-hidden transition-all duration-300 ease-in"
     >
       <div
+        :class="{
+          'shadow-[0_16px_24px_hsl(var(--background))]': scrollY > 20,
+        }"
         :style="headerWrapperStyle"
-        class="overflow-hidden shadow-[0_16px_24px_hsl(var(--background))] transition-all duration-200"
+        class="overflow-hidden transition-all duration-200"
       >
         <LayoutHeader
           v-if="headerVisible"
           :full-width="!isSideMode"
           :height="headerHeight"
-          :is-mixed-nav="isMixedNav"
           :is-mobile="isMobile"
           :show="!isFullContent && !headerHidden"
-          :show-toggle-btn="showHeaderToggleButton"
           :sidebar-width="sidebarWidth"
           :theme="headerTheme"
           :width="mainStyle.width"
           :z-index="headerZIndex"
-          @open-menu="handleOpenMenu"
-          @toggle-sidebar="() => emit('toggleSidebar')"
         >
           <template v-if="showHeaderLogo" #logo>
             <slot name="logo"></slot>
           </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>
         </LayoutHeader>
 

+ 1 - 1
packages/@core/ui-kit/menu-ui/src/components/menu-item.vue

@@ -1,5 +1,5 @@
 <script lang="ts" setup>
-import type { MenuItemProps, MenuItemRegistered } from '../interface';
+import type { MenuItemProps, MenuItemRegistered } from '../types';
 
 import { computed, onBeforeUnmount, onMounted, reactive, useSlots } from 'vue';
 

+ 1 - 1
packages/@core/ui-kit/menu-ui/src/components/menu.vue

@@ -6,7 +6,7 @@ import type {
   MenuItemRegistered,
   MenuProps,
   MenuProvider,
-} from '../interface';
+} from '../types';
 
 import {
   computed,

+ 1 - 1
packages/@core/ui-kit/menu-ui/src/components/sub-menu-content.vue

@@ -1,5 +1,5 @@
 <script lang="ts" setup>
-import type { MenuItemProps } from '../interface';
+import type { MenuItemProps } from '../types';
 
 import { computed } from 'vue';
 

+ 2 - 7
packages/@core/ui-kit/menu-ui/src/components/sub-menu.vue

@@ -1,11 +1,7 @@
 <script lang="ts" setup>
 import type { HoverCardContentProps } from '@vben-core/shadcn-ui';
 
-import type {
-  MenuItemRegistered,
-  MenuProvider,
-  SubMenuProps,
-} from '../interface';
+import type { MenuItemRegistered, MenuProvider, SubMenuProps } from '../types';
 
 import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue';
 
@@ -74,7 +70,6 @@ const contentProps = computed((): HoverCardContentProps => {
     collisionPadding: { top: 20 },
     side,
     sideOffset: isHorizontal ? 5 : 10,
-    // sideOffset: 10,
   };
 });
 
@@ -216,7 +211,7 @@ onBeforeUnmount(() => {
         ]"
         :content-props="contentProps"
         :open="true"
-        :open-delay="30"
+        :open-delay="0"
       >
         <template #trigger>
           <SubMenuContent

+ 1 - 1
packages/@core/ui-kit/menu-ui/src/hooks/use-menu-context.ts

@@ -1,4 +1,4 @@
-import type { MenuProvider, SubMenuProvider } from '../interface';
+import type { MenuProvider, SubMenuProvider } from '../types';
 
 import { getCurrentInstance, inject, provide } from 'vue';
 

+ 1 - 1
packages/@core/ui-kit/menu-ui/src/hooks/use-menu.ts

@@ -1,4 +1,4 @@
-import type { SubMenuProvider } from '../interface';
+import type { SubMenuProvider } from '../types';
 
 import { computed, getCurrentInstance } from 'vue';
 

+ 1 - 1
packages/@core/ui-kit/menu-ui/src/index.ts

@@ -1,3 +1,3 @@
 export * from './components/normal-menu';
-export type * from './interface';
 export { default as Menu } from './menu.vue';
+export type * from './types';

+ 1 - 1
packages/@core/ui-kit/menu-ui/src/menu.vue

@@ -1,7 +1,7 @@
 <script setup lang="ts">
 import type { MenuRecordRaw } from '@vben-core/typings';
 
-import type { MenuProps } from './interface';
+import type { MenuProps } from './types';
 
 import { useForwardProps } from '@vben-core/composables';
 

+ 0 - 0
packages/@core/ui-kit/menu-ui/src/interface/index.ts → packages/@core/ui-kit/menu-ui/src/types.ts


+ 1 - 13
packages/@core/ui-kit/tabs-ui/src/components/tabs-chrome/tabs.vue

@@ -121,7 +121,7 @@ const tabsView = computed((): TabConfig[] => {
               />
               <Pin
                 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)"
               />
             </div>
@@ -150,18 +150,6 @@ const tabsView = computed((): TabConfig[] => {
 
 <style scoped>
 .tabs-chrome {
-  /* .dragging { */
-
-  /* .tabs-chrome__item-main {
-      @apply pr-0;
-    } */
-
-  /* .tabs-chrome__extra {
-      @apply hidden;
-    } */
-
-  /* } */
-
   &__item:not(.dragging) {
     @apply cursor-pointer;
 

+ 1 - 1
packages/@core/ui-kit/tabs-ui/src/components/tabs/tabs.vue

@@ -100,7 +100,7 @@ const tabsView = computed((): TabConfig[] => {
               />
               <Pin
                 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)"
               />
             </div>

+ 3 - 1
packages/effects/hooks/src/use-design-tokens.ts

@@ -18,6 +18,7 @@ export function useAntdDesignTokens() {
     colorBgLayout: '',
     colorBgMask: '',
     colorBorder: '',
+    colorBorderSecondary: '',
     colorError: '',
     colorInfo: '',
     colorPrimary: '',
@@ -48,7 +49,8 @@ export function useAntdDesignTokens() {
 
       getCssVariableValue('--primary-foreground');
 
-      tokens.colorBorder = getCssVariableValue('--border');
+      tokens.colorBorderSecondary = tokens.colorBorder =
+        getCssVariableValue('--border');
 
       tokens.colorBgElevated = getCssVariableValue('--popover');
 

+ 8 - 8
packages/stores/src/modules/tabbar.ts

@@ -47,7 +47,7 @@ export const useTabbarStore = defineStore('core-tabbar', {
         return !paths.includes(getTabPath(item));
       });
 
-      this.updateCacheTab();
+      this.updateCacheTabs();
     },
     /**
      * @zh_CN 关闭标签页
@@ -141,7 +141,7 @@ export const useTabbarStore = defineStore('core-tabbar', {
 
         this.tabs.splice(tabIndex, 1, mergedTab);
       }
-      this.updateCacheTab();
+      this.updateCacheTabs();
     },
     /**
      * @zh_CN 关闭所有标签页
@@ -150,7 +150,7 @@ export const useTabbarStore = defineStore('core-tabbar', {
       const newTabs = this.tabs.filter((tab) => isAffixTab(tab));
       this.tabs = newTabs.length > 0 ? newTabs : [...this.tabs].splice(0, 1);
       await this._goToDefaultTab(router);
-      this.updateCacheTab();
+      this.updateCacheTabs();
     },
     /**
      * @zh_CN 关闭左侧标签页
@@ -230,7 +230,7 @@ export const useTabbarStore = defineStore('core-tabbar', {
       // 关闭不是激活选项卡
       if (getTabPath(currentRoute.value) !== getTabPath(tab)) {
         this._close(tab);
-        this.updateCacheTab();
+        this.updateCacheTabs();
         return;
       }
       const index = this.getTabs.findIndex(
@@ -339,7 +339,7 @@ export const useTabbarStore = defineStore('core-tabbar', {
       );
       if (findTab) {
         findTab.meta.newTabTitle = undefined;
-        await this.updateCacheTab();
+        await this.updateCacheTabs();
       }
     },
 
@@ -367,7 +367,7 @@ export const useTabbarStore = defineStore('core-tabbar', {
       if (findTab) {
         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>();
 
       for (const tab of this.tabs) {
@@ -426,7 +426,7 @@ export const useTabbarStore = defineStore('core-tabbar', {
         if (!keepAlive) {
           continue;
         }
-        tab.matched.forEach((t, i) => {
+        (tab.matched || []).forEach((t, i) => {
           if (i > 0) {
             cacheMap.add(t.name as string);
           }

+ 5 - 0
packages/styles/src/antd/index.css

@@ -6,3 +6,8 @@
   overscroll-behavior: none;
   color: inherit;
 }
+
+.ant-message-notice-content,
+.ant-notification-notice {
+  @apply dark:border-border/60 dark:border;
+}

+ 1 - 1
playground/.env

@@ -2,4 +2,4 @@
 VITE_APP_TITLE=Vben Admin
 
 # 应用命名空间,用于缓存、store等功能的前缀,确保隔离
-VITE_APP_NAMESPACE=vben-web-antd
+VITE_APP_NAMESPACE=vben-web-play