diff --git a/apps/web-antd/src/app.vue b/apps/web-antd/src/app.vue
index 057dd581..bbaccce1 100644
--- a/apps/web-antd/src/app.vue
+++ b/apps/web-antd/src/app.vue
@@ -1,7 +1,7 @@
diff --git a/apps/web-naive/.env b/apps/web-naive/.env
new file mode 100644
index 00000000..350660c0
--- /dev/null
+++ b/apps/web-naive/.env
@@ -0,0 +1,5 @@
+# 应用标题
+VITE_APP_TITLE=Vben Admin Naive
+
+# 应用命名空间,用于缓存、store等功能的前缀,确保隔离
+VITE_APP_NAMESPACE=vben-web-naive
diff --git a/apps/web-naive/.env.analyze b/apps/web-naive/.env.analyze
new file mode 100644
index 00000000..ffafa8dd
--- /dev/null
+++ b/apps/web-naive/.env.analyze
@@ -0,0 +1,7 @@
+# public path
+VITE_BASE=/
+
+# Basic interface address SPA
+VITE_GLOB_API_URL=/api
+
+VITE_VISUALIZER=true
diff --git a/apps/web-naive/.env.development b/apps/web-naive/.env.development
new file mode 100644
index 00000000..9e06fb64
--- /dev/null
+++ b/apps/web-naive/.env.development
@@ -0,0 +1,16 @@
+# 端口号
+VITE_PORT=5566
+
+VITE_BASE=/
+
+# 接口地址
+VITE_GLOB_API_URL=/api
+
+# 是否开启 Nitro Mock服务,true 为开启,false 为关闭
+VITE_NITRO_MOCK=true
+
+# 是否打开 devtools,true 为打开,false 为关闭
+VITE_DEVTOOLS=false
+
+# 是否注入全局loading
+VITE_INJECT_APP_LOADING=true
diff --git a/apps/web-naive/.env.production b/apps/web-naive/.env.production
new file mode 100644
index 00000000..8f979f58
--- /dev/null
+++ b/apps/web-naive/.env.production
@@ -0,0 +1,16 @@
+VITE_BASE=/
+
+# 接口地址
+VITE_GLOB_API_URL=https://mock-napi.vben.pro/api
+
+# 是否开启压缩,可以设置为 none, brotli, gzip
+VITE_COMPRESS=none
+
+# 是否开启 PWA
+VITE_PWA=true
+
+# vue-router 的模式
+VITE_ROUTER_HISTORY=hash
+
+# 是否注入全局loading
+VITE_INJECT_APP_LOADING=true
diff --git a/apps/web-naive/index.html b/apps/web-naive/index.html
new file mode 100644
index 00000000..ca532699
--- /dev/null
+++ b/apps/web-naive/index.html
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+ <%= VITE_APP_TITLE %>
+
+
+
+
+
+
+
+
diff --git a/apps/web-naive/package.json b/apps/web-naive/package.json
new file mode 100644
index 00000000..3360c0a8
--- /dev/null
+++ b/apps/web-naive/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "@vben/web-naive",
+ "version": "5.0.0",
+ "homepage": "https://vben.pro",
+ "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/vbenjs/vue-vben-admin.git",
+ "directory": "apps/web-naive"
+ },
+ "license": "MIT",
+ "author": {
+ "name": "vben",
+ "email": "ann.vben@gmail.com",
+ "url": "https://github.com/anncwb"
+ },
+ "type": "module",
+ "scripts": {
+ "build": "pnpm vite build --mode production",
+ "build:analyze": "pnpm vite build --mode analyze",
+ "dev": "pnpm vite --mode development",
+ "preview": "vite preview",
+ "typecheck": "vue-tsc --noEmit --skipLibCheck"
+ },
+ "imports": {
+ "#/*": "./src/*"
+ },
+ "dependencies": {
+ "@vben/access": "workspace:*",
+ "@vben/chart-ui": "workspace:*",
+ "@vben/common-ui": "workspace:*",
+ "@vben/constants": "workspace:*",
+ "@vben/hooks": "workspace:*",
+ "@vben/icons": "workspace:*",
+ "@vben/layouts": "workspace:*",
+ "@vben/locales": "workspace:*",
+ "@vben/preferences": "workspace:*",
+ "@vben/request": "workspace:*",
+ "@vben/stores": "workspace:*",
+ "@vben/styles": "workspace:*",
+ "@vben/types": "workspace:*",
+ "@vben/utils": "workspace:*",
+ "@vueuse/core": "^10.11.0",
+ "naive-ui": "^2.39.0",
+ "pinia": "2.1.7",
+ "vue": "^3.4.34",
+ "vue-router": "^4.4.0"
+ }
+}
diff --git a/apps/web-naive/postcss.config.mjs b/apps/web-naive/postcss.config.mjs
new file mode 100644
index 00000000..3d807045
--- /dev/null
+++ b/apps/web-naive/postcss.config.mjs
@@ -0,0 +1 @@
+export { default } from '@vben/tailwind-config/postcss';
diff --git a/apps/web-naive/public/favicon.ico b/apps/web-naive/public/favicon.ico
new file mode 100644
index 00000000..fcf9818e
Binary files /dev/null and b/apps/web-naive/public/favicon.ico differ
diff --git a/apps/web-naive/src/api/core/auth.ts b/apps/web-naive/src/api/core/auth.ts
new file mode 100644
index 00000000..6950e3bf
--- /dev/null
+++ b/apps/web-naive/src/api/core/auth.ts
@@ -0,0 +1,33 @@
+import { requestClient } from '#/api/request';
+
+export namespace AuthApi {
+ /** 登录接口参数 */
+ export interface LoginParams {
+ password: string;
+ username: string;
+ }
+
+ /** 登录接口返回值 */
+ export interface LoginResult {
+ accessToken: string;
+ desc: string;
+ realName: string;
+ refreshToken: string;
+ userId: string;
+ username: string;
+ }
+}
+
+/**
+ * 登录
+ */
+export async function login(data: AuthApi.LoginParams) {
+ return requestClient.post('/auth/login', data);
+}
+
+/**
+ * 获取用户权限码
+ */
+export async function getAccessCodes() {
+ return requestClient.get('/auth/codes');
+}
diff --git a/apps/web-naive/src/api/core/index.ts b/apps/web-naive/src/api/core/index.ts
new file mode 100644
index 00000000..28a5aef4
--- /dev/null
+++ b/apps/web-naive/src/api/core/index.ts
@@ -0,0 +1,3 @@
+export * from './auth';
+export * from './menu';
+export * from './user';
diff --git a/apps/web-naive/src/api/core/menu.ts b/apps/web-naive/src/api/core/menu.ts
new file mode 100644
index 00000000..62c40f17
--- /dev/null
+++ b/apps/web-naive/src/api/core/menu.ts
@@ -0,0 +1,10 @@
+import type { RouteRecordStringComponent } from '@vben/types';
+
+import { requestClient } from '#/api/request';
+
+/**
+ * 获取用户所有菜单
+ */
+export async function getAllMenus() {
+ return requestClient.get('/menu/all');
+}
diff --git a/apps/web-naive/src/api/core/user.ts b/apps/web-naive/src/api/core/user.ts
new file mode 100644
index 00000000..34c14ea9
--- /dev/null
+++ b/apps/web-naive/src/api/core/user.ts
@@ -0,0 +1,10 @@
+import type { UserInfo } from '@vben/types';
+
+import { requestClient } from '#/api/request';
+
+/**
+ * 获取用户信息
+ */
+export async function getUserInfo() {
+ return requestClient.get('/user/info');
+}
diff --git a/apps/web-naive/src/api/index.ts b/apps/web-naive/src/api/index.ts
new file mode 100644
index 00000000..4b0e0413
--- /dev/null
+++ b/apps/web-naive/src/api/index.ts
@@ -0,0 +1 @@
+export * from './core';
diff --git a/apps/web-naive/src/api/request.ts b/apps/web-naive/src/api/request.ts
new file mode 100644
index 00000000..524576be
--- /dev/null
+++ b/apps/web-naive/src/api/request.ts
@@ -0,0 +1,66 @@
+/**
+ * 该文件可自行根据业务逻辑进行调整
+ */
+import type { HttpResponse } from '@vben/request';
+
+import { useAppConfig } from '@vben/hooks';
+import { preferences } from '@vben/preferences';
+import { RequestClient } from '@vben/request';
+import { useAccessStore } from '@vben/stores';
+
+import { message } from '#/naive';
+import { useAuthStore } from '#/store';
+
+const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD);
+
+function createRequestClient(baseURL: string) {
+ const client = new RequestClient({
+ baseURL,
+ // 为每个请求携带 Authorization
+ makeAuthorization: () => {
+ return {
+ // 默认
+ key: 'Authorization',
+ tokenHandler: () => {
+ const accessStore = useAccessStore();
+ return {
+ refreshToken: `${accessStore.refreshToken}`,
+ token: `${accessStore.accessToken}`,
+ };
+ },
+ unAuthorizedHandler: async () => {
+ const accessStore = useAccessStore();
+ const authStore = useAuthStore();
+ accessStore.setAccessToken(null);
+
+ if (preferences.app.loginExpiredMode === 'modal') {
+ accessStore.setLoginExpired(true);
+ } else {
+ // 退出登录
+ await authStore.logout();
+ }
+ },
+ };
+ },
+ makeErrorMessage: (msg) => message.error(msg),
+
+ makeRequestHeaders: () => {
+ return {
+ // 为每个请求携带 Accept-Language
+ 'Accept-Language': preferences.app.locale,
+ };
+ },
+ });
+ client.addResponseInterceptor((response) => {
+ const { data: responseData, status } = response;
+
+ const { code, data, message: msg } = responseData;
+ if (status >= 200 && status < 400 && code === 0) {
+ return data;
+ }
+ throw new Error(msg);
+ });
+ return client;
+}
+
+export const requestClient = createRequestClient(apiURL);
diff --git a/apps/web-naive/src/app.vue b/apps/web-naive/src/app.vue
new file mode 100644
index 00000000..76e82a05
--- /dev/null
+++ b/apps/web-naive/src/app.vue
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/web-naive/src/bootstrap.ts b/apps/web-naive/src/bootstrap.ts
new file mode 100644
index 00000000..850b5658
--- /dev/null
+++ b/apps/web-naive/src/bootstrap.ts
@@ -0,0 +1,35 @@
+import { createApp } from 'vue';
+
+import { registerAccessDirective } from '@vben/access';
+import { initStores } from '@vben/stores';
+import '@vben/styles';
+import '@vben/styles/antd';
+
+import naive from 'naive-ui';
+
+import { setupI18n } from '#/locales';
+
+import App from './app.vue';
+import { router } from './router';
+
+async function bootstrap(namespace: string) {
+ const app = createApp(App);
+
+ // 国际化 i18n 配置
+ await setupI18n(app);
+
+ // 配置 pinia-tore
+ await initStores(app, { namespace });
+
+ // 安装权限指令
+ registerAccessDirective(app);
+
+ // 配置路由及路由守卫
+ app.use(router);
+
+ app.use(naive);
+
+ app.mount('#app');
+}
+
+export { bootstrap };
diff --git a/apps/web-naive/src/layouts/basic.vue b/apps/web-naive/src/layouts/basic.vue
new file mode 100644
index 00000000..ab1832c2
--- /dev/null
+++ b/apps/web-naive/src/layouts/basic.vue
@@ -0,0 +1,153 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/web-naive/src/layouts/index.ts b/apps/web-naive/src/layouts/index.ts
new file mode 100644
index 00000000..23d79d6e
--- /dev/null
+++ b/apps/web-naive/src/layouts/index.ts
@@ -0,0 +1,8 @@
+const BasicLayout = () => import('./basic.vue');
+
+const IFrameView = () => import('@vben/layouts').then((m) => m.IFrameView);
+
+const AuthPageLayout = () =>
+ import('@vben/layouts').then((m) => m.AuthPageLayout);
+
+export { AuthPageLayout, BasicLayout, IFrameView };
diff --git a/apps/web-naive/src/locales/README.md b/apps/web-naive/src/locales/README.md
new file mode 100644
index 00000000..7b451032
--- /dev/null
+++ b/apps/web-naive/src/locales/README.md
@@ -0,0 +1,3 @@
+# locale
+
+每个app使用的国际化可能不同,这里用于扩展国际化的功能,例如扩展 dayjs、antd组件库的多语言切换,以及app本身的国际化文件。
diff --git a/apps/web-naive/src/locales/index.ts b/apps/web-naive/src/locales/index.ts
new file mode 100644
index 00000000..056c4434
--- /dev/null
+++ b/apps/web-naive/src/locales/index.ts
@@ -0,0 +1,31 @@
+import type { LocaleSetupOptions, SupportedLanguagesType } from '@vben/locales';
+
+import type { App } from 'vue';
+
+import { $t, setupI18n as coreSetup, loadLocalesMap } from '@vben/locales';
+import { preferences } from '@vben/preferences';
+
+const modules = import.meta.glob('./langs/*.json');
+
+const localesMap = loadLocalesMap(modules);
+
+/**
+ * 加载应用特有的语言包
+ * 这里也可以改造为从服务端获取翻译数据
+ * @param lang
+ */
+async function loadMessages(lang: SupportedLanguagesType) {
+ const appLocaleMessages = await localesMap[lang]();
+ return appLocaleMessages.default;
+}
+
+async function setupI18n(app: App, options: LocaleSetupOptions = {}) {
+ await coreSetup(app, {
+ defaultLocale: preferences.app.locale,
+ loadMessages,
+ missingWarn: !import.meta.env.PROD,
+ ...options,
+ });
+}
+
+export { $t, loadMessages, setupI18n };
diff --git a/apps/web-naive/src/locales/langs/en-US.json b/apps/web-naive/src/locales/langs/en-US.json
new file mode 100644
index 00000000..5f48dc4c
--- /dev/null
+++ b/apps/web-naive/src/locales/langs/en-US.json
@@ -0,0 +1,8 @@
+{
+ "page": {
+ "demos": {
+ "title": "Demos",
+ "naive": "Naive UI"
+ }
+ }
+}
diff --git a/apps/web-naive/src/locales/langs/zh-CN.json b/apps/web-naive/src/locales/langs/zh-CN.json
new file mode 100644
index 00000000..69b85185
--- /dev/null
+++ b/apps/web-naive/src/locales/langs/zh-CN.json
@@ -0,0 +1,8 @@
+{
+ "page": {
+ "demos": {
+ "title": "演示",
+ "naive": "Naive UI"
+ }
+ }
+}
diff --git a/apps/web-naive/src/main.ts b/apps/web-naive/src/main.ts
new file mode 100644
index 00000000..5d728a02
--- /dev/null
+++ b/apps/web-naive/src/main.ts
@@ -0,0 +1,31 @@
+import { initPreferences } from '@vben/preferences';
+import { unmountGlobalLoading } from '@vben/utils';
+
+import { overridesPreferences } from './preferences';
+
+/**
+ * 应用初始化完成之后再进行页面加载渲染
+ */
+async function initApplication() {
+ // name用于指定项目唯一标识
+ // 用于区分不同项目的偏好设置以及存储数据的key前缀以及其他一些需要隔离的数据
+ const env = import.meta.env.PROD ? 'prod' : 'dev';
+ const appVersion = import.meta.env.VITE_APP_VERSION;
+ const namespace = `${import.meta.env.VITE_APP_NAMESPACE}-${appVersion}-${env}`;
+
+ // app偏好设置初始化
+ await initPreferences({
+ namespace,
+ overrides: overridesPreferences,
+ });
+
+ // 启动应用并挂载
+ // vue应用主要逻辑及视图
+ const { bootstrap } = await import('./bootstrap');
+ await bootstrap(namespace);
+
+ // 移除并销毁loading
+ unmountGlobalLoading();
+}
+
+initApplication();
diff --git a/apps/web-naive/src/naive.ts b/apps/web-naive/src/naive.ts
new file mode 100644
index 00000000..1eb7b7b6
--- /dev/null
+++ b/apps/web-naive/src/naive.ts
@@ -0,0 +1,25 @@
+import { computed } from 'vue';
+
+import { preferences } from '@vben/preferences';
+import '@vben/styles';
+
+import { createDiscreteApi, darkTheme, lightTheme } from 'naive-ui';
+
+const themeOverridesProviderProps = computed(() => ({
+ themeOverrides: preferences.theme.mode === 'light' ? lightTheme : darkTheme,
+}));
+
+const themeProviderProps = computed(() => ({
+ theme: preferences.theme.mode === 'light' ? lightTheme : darkTheme,
+}));
+
+export const { dialog, loadingBar, message, modal, notification } =
+ createDiscreteApi(
+ ['message', 'dialog', 'notification', 'loadingBar', 'modal'],
+ {
+ configProviderProps: themeProviderProps,
+ loadingBarProviderProps: themeOverridesProviderProps,
+ messageProviderProps: themeOverridesProviderProps,
+ notificationProviderProps: themeOverridesProviderProps,
+ },
+ );
diff --git a/apps/web-naive/src/preferences.ts b/apps/web-naive/src/preferences.ts
new file mode 100644
index 00000000..9683596a
--- /dev/null
+++ b/apps/web-naive/src/preferences.ts
@@ -0,0 +1,9 @@
+import { defineOverridesPreferences } from '@vben/preferences';
+
+/**
+ * @description 项目配置文件
+ * 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置
+ */
+export const overridesPreferences = defineOverridesPreferences({
+ // overrides
+});
diff --git a/apps/web-naive/src/router/access.ts b/apps/web-naive/src/router/access.ts
new file mode 100644
index 00000000..503a645c
--- /dev/null
+++ b/apps/web-naive/src/router/access.ts
@@ -0,0 +1,40 @@
+import type {
+ ComponentRecordType,
+ GenerateMenuAndRoutesOptions,
+} from '@vben/types';
+
+import { generateAccessible } from '@vben/access';
+import { preferences } from '@vben/preferences';
+
+import { getAllMenus } from '#/api';
+import { BasicLayout, IFrameView } from '#/layouts';
+import { $t } from '#/locales';
+import { message } from '#/naive';
+
+const forbiddenComponent = () => import('#/views/_core/fallback/forbidden.vue');
+
+async function generateAccess(options: GenerateMenuAndRoutesOptions) {
+ const pageMap: ComponentRecordType = import.meta.glob('../views/**/*.vue');
+
+ const layoutMap: ComponentRecordType = {
+ BasicLayout,
+ IFrameView,
+ };
+
+ return await generateAccessible(preferences.app.accessMode, {
+ ...options,
+ fetchMenuListAsync: async () => {
+ message.loading(`${$t('common.loadingMenu')}...`, {
+ duration: 1.5,
+ });
+ return await getAllMenus();
+ },
+ // 可以指定没有权限跳转403页面
+ forbiddenComponent,
+ // 如果 route.meta.menuVisibleWithForbidden = true
+ layoutMap,
+ pageMap,
+ });
+}
+
+export { generateAccess };
diff --git a/apps/web-naive/src/router/guard.ts b/apps/web-naive/src/router/guard.ts
new file mode 100644
index 00000000..6bf46a60
--- /dev/null
+++ b/apps/web-naive/src/router/guard.ts
@@ -0,0 +1,132 @@
+import type { Router } from 'vue-router';
+
+import { LOGIN_PATH } from '@vben/constants';
+import { preferences } from '@vben/preferences';
+import { useAccessStore, useUserStore } from '@vben/stores';
+import { startProgress, stopProgress } from '@vben/utils';
+
+import { useTitle } from '@vueuse/core';
+
+import { $t } from '#/locales';
+import { coreRouteNames, dynamicRoutes } from '#/router/routes';
+import { useAuthStore } from '#/store';
+
+import { generateAccess } from './access';
+
+/**
+ * 通用守卫配置
+ * @param router
+ */
+function setupCommonGuard(router: Router) {
+ // 记录已经加载的页面
+ const loadedPaths = new Set();
+
+ router.beforeEach(async (to) => {
+ to.meta.loaded = loadedPaths.has(to.path);
+
+ // 页面加载进度条
+ if (!to.meta.loaded && preferences.transition.progress) {
+ startProgress();
+ }
+ return true;
+ });
+
+ router.afterEach((to) => {
+ // 记录页面是否加载,如果已经加载,后续的页面切换动画等效果不在重复执行
+
+ if (preferences.tabbar.enable) {
+ loadedPaths.add(to.path);
+ }
+
+ // 关闭页面加载进度条
+ if (preferences.transition.progress) {
+ stopProgress();
+ }
+
+ // 动态修改标题
+ if (preferences.app.dynamicTitle) {
+ const { title } = to.meta;
+ // useTitle(`${$t(title)} - ${preferences.app.name}`);
+ useTitle(`${$t(title)} - ${preferences.app.name}`);
+ }
+ });
+}
+
+/**
+ * 权限访问守卫配置
+ * @param router
+ */
+function setupAccessGuard(router: Router) {
+ router.beforeEach(async (to, from) => {
+ const accessStore = useAccessStore();
+ const userStore = useUserStore();
+ const authStore = useAuthStore();
+
+ // accessToken 检查
+ if (!accessStore.accessToken) {
+ if (
+ // 基本路由,这些路由不需要进入权限拦截
+ coreRouteNames.includes(to.name as string) ||
+ // 明确声明忽略权限访问权限,则可以访问
+ to.meta.ignoreAccess
+ ) {
+ return true;
+ }
+
+ // 没有访问权限,跳转登录页面
+ if (to.fullPath !== LOGIN_PATH) {
+ return {
+ path: LOGIN_PATH,
+ // 如不需要,直接删除 query
+ query: { redirect: encodeURIComponent(to.fullPath) },
+ // 携带当前跳转的页面,登录后重新跳转该页面
+ replace: true,
+ };
+ }
+ return to;
+ }
+
+ const accessRoutes = accessStore.accessRoutes;
+
+ // 是否已经生成过动态路由
+ if (accessRoutes && accessRoutes.length > 0) {
+ return true;
+ }
+
+ // 生成路由表
+ // 当前登录用户拥有的角色标识列表
+ const userInfo = userStore.userInfo || (await authStore.fetchUserInfo());
+ const userRoles = userInfo.roles ?? [];
+
+ // 生成菜单和路由
+ const { accessibleMenus, accessibleRoutes } = await generateAccess({
+ roles: userRoles,
+ router,
+ // 则会在菜单中显示,但是访问会被重定向到403
+ routes: dynamicRoutes,
+ });
+
+ // 保存菜单信息和路由信息
+ accessStore.setAccessMenus(accessibleMenus);
+ accessStore.setAccessRoutes(accessibleRoutes);
+ const redirectPath = (from.query.redirect ?? to.path) as string;
+
+ return {
+ path: decodeURIComponent(redirectPath),
+ replace: true,
+ };
+ });
+}
+
+/**
+ * 项目守卫配置
+ * @param router
+ */
+function createRouterGuard(router: Router) {
+ /** 通用 */
+ setupCommonGuard(router);
+ /** 权限访问 */
+ setupAccessGuard(router);
+}
+
+export { createRouterGuard };
diff --git a/apps/web-naive/src/router/index.ts b/apps/web-naive/src/router/index.ts
new file mode 100644
index 00000000..313b372b
--- /dev/null
+++ b/apps/web-naive/src/router/index.ts
@@ -0,0 +1,32 @@
+import {
+ createRouter,
+ createWebHashHistory,
+ createWebHistory,
+} from 'vue-router';
+
+import { resetStaticRoutes } from '@vben/utils';
+
+import { createRouterGuard } from './guard';
+import { routes } from './routes';
+
+/**
+ * @zh_CN 创建vue-router实例
+ */
+const router = createRouter({
+ history:
+ import.meta.env.VITE_ROUTER_HISTORY === 'hash'
+ ? createWebHashHistory(import.meta.env.VITE_BASE)
+ : createWebHistory(import.meta.env.VITE_BASE),
+ // 应该添加到路由的初始路由列表。
+ routes,
+ scrollBehavior: () => ({ left: 0, top: 0 }),
+ // 是否应该禁止尾部斜杠。
+ // strict: true,
+});
+
+const resetRoutes = () => resetStaticRoutes(router, routes);
+
+// 创建路由守卫
+createRouterGuard(router);
+
+export { resetRoutes, router };
diff --git a/apps/web-naive/src/router/routes/core.ts b/apps/web-naive/src/router/routes/core.ts
new file mode 100644
index 00000000..f793a57e
--- /dev/null
+++ b/apps/web-naive/src/router/routes/core.ts
@@ -0,0 +1,86 @@
+import type { RouteRecordRaw } from 'vue-router';
+
+import { DEFAULT_HOME_PATH } from '@vben/constants';
+
+import { AuthPageLayout } from '#/layouts';
+import { $t } from '#/locales';
+import Login from '#/views/_core/authentication/login.vue';
+
+/** 全局404页面 */
+const fallbackNotFoundRoute: RouteRecordRaw = {
+ component: () => import('#/views/_core/fallback/not-found.vue'),
+ meta: {
+ hideInBreadcrumb: true,
+ hideInMenu: true,
+ hideInTab: true,
+ title: '404',
+ },
+ name: 'FallbackNotFound',
+ path: '/:path(.*)*',
+};
+
+/** 基本路由,这些路由是必须存在的 */
+const coreRoutes: RouteRecordRaw[] = [
+ {
+ meta: {
+ title: 'Root',
+ },
+ name: 'Root',
+ path: '/',
+ redirect: DEFAULT_HOME_PATH,
+ },
+ {
+ component: AuthPageLayout,
+ meta: {
+ title: 'Authentication',
+ },
+ name: 'Authentication',
+ path: '/auth',
+ children: [
+ {
+ name: 'Login',
+ path: 'login',
+ component: Login,
+ meta: {
+ title: $t('page.core.login'),
+ },
+ },
+ {
+ name: 'CodeLogin',
+ path: 'code-login',
+ component: () => import('#/views/_core/authentication/code-login.vue'),
+ meta: {
+ title: $t('page.core.codeLogin'),
+ },
+ },
+ {
+ name: 'QrCodeLogin',
+ path: 'qrcode-login',
+ component: () =>
+ import('#/views/_core/authentication/qrcode-login.vue'),
+ meta: {
+ title: $t('page.core.qrcodeLogin'),
+ },
+ },
+ {
+ name: 'ForgetPassword',
+ path: 'forget-password',
+ component: () =>
+ import('#/views/_core/authentication/forget-password.vue'),
+ meta: {
+ title: $t('page.core.forgetPassword'),
+ },
+ },
+ {
+ name: 'Register',
+ path: 'register',
+ component: () => import('#/views/_core/authentication/register.vue'),
+ meta: {
+ title: $t('page.core.register'),
+ },
+ },
+ ],
+ },
+];
+
+export { coreRoutes, fallbackNotFoundRoute };
diff --git a/apps/web-naive/src/router/routes/index.ts b/apps/web-naive/src/router/routes/index.ts
new file mode 100644
index 00000000..78da5436
--- /dev/null
+++ b/apps/web-naive/src/router/routes/index.ts
@@ -0,0 +1,31 @@
+import type { RouteRecordRaw } from 'vue-router';
+
+import { mergeRouteModules, traverseTreeValues } from '@vben/utils';
+
+import { coreRoutes, fallbackNotFoundRoute } from './core';
+
+const dynamicRouteFiles = import.meta.glob('./modules/**/*.ts', {
+ eager: true,
+});
+
+// 有需要可以自行打开注释,并创建文件夹
+// const staticRouteFiles = import.meta.glob('./static/**/*.ts', { eager: true });
+
+/** 动态路由 */
+const dynamicRoutes: RouteRecordRaw[] = mergeRouteModules(dynamicRouteFiles);
+
+/** 静态路由列表,访问这些页面可以不需要权限 */
+// const staticRoutes: RouteRecordRaw[] = mergeRouteModules(staticRouteFiles);
+const staticRoutes: RouteRecordRaw[] = [];
+
+/** 路由列表,由基本路由+静态路由组成 */
+const routes: RouteRecordRaw[] = [
+ ...coreRoutes,
+ ...staticRoutes,
+ fallbackNotFoundRoute,
+];
+
+/** 基本路由列表,这些路由不需要进入权限拦截 */
+const coreRouteNames = traverseTreeValues(coreRoutes, (route) => route.name);
+
+export { coreRouteNames, dynamicRoutes, routes };
diff --git a/apps/web-naive/src/router/routes/modules/dashboard.ts b/apps/web-naive/src/router/routes/modules/dashboard.ts
new file mode 100644
index 00000000..a8cdb05d
--- /dev/null
+++ b/apps/web-naive/src/router/routes/modules/dashboard.ts
@@ -0,0 +1,39 @@
+import type { RouteRecordRaw } from 'vue-router';
+
+import { BasicLayout } from '#/layouts';
+import { $t } from '#/locales';
+
+const routes: RouteRecordRaw[] = [
+ {
+ component: BasicLayout,
+ meta: {
+ icon: 'lucide:layout-dashboard',
+ order: -1,
+ title: $t('page.dashboard.title'),
+ },
+ name: 'Dashboard',
+ path: '/',
+ children: [
+ {
+ name: 'Analytics',
+ path: '/analytics',
+ component: () => import('#/views/dashboard/analytics/index.vue'),
+ meta: {
+ affixTab: true,
+ icon: 'lucide:area-chart',
+ title: $t('page.dashboard.analytics'),
+ },
+ },
+ {
+ name: 'Workspace',
+ path: '/workspace',
+ component: () => import('#/views/dashboard/workspace/index.vue'),
+ meta: {
+ title: $t('page.dashboard.workspace'),
+ },
+ },
+ ],
+ },
+];
+
+export default routes;
diff --git a/apps/web-naive/src/router/routes/modules/demos.ts b/apps/web-naive/src/router/routes/modules/demos.ts
new file mode 100644
index 00000000..a418887a
--- /dev/null
+++ b/apps/web-naive/src/router/routes/modules/demos.ts
@@ -0,0 +1,32 @@
+import type { RouteRecordRaw } from 'vue-router';
+
+import { BasicLayout } from '#/layouts';
+import { $t } from '#/locales';
+
+const routes: RouteRecordRaw[] = [
+ {
+ component: BasicLayout,
+ meta: {
+ icon: 'ic:baseline-view-in-ar',
+ keepAlive: true,
+ order: 1000,
+ title: $t('page.demos.title'),
+ },
+ name: 'Demos',
+ path: '/demos',
+ children: [
+ // 权限控制
+ {
+ meta: {
+ icon: 'mdi:shield-key-outline',
+ title: $t('page.demos.naive'),
+ },
+ name: 'NaiveDemos',
+ path: '/demos/access',
+ component: () => import('#/views/demos/naive/index.vue'),
+ },
+ ],
+ },
+];
+
+export default routes;
diff --git a/apps/web-naive/src/router/routes/modules/vben.ts b/apps/web-naive/src/router/routes/modules/vben.ts
new file mode 100644
index 00000000..7df7268b
--- /dev/null
+++ b/apps/web-naive/src/router/routes/modules/vben.ts
@@ -0,0 +1,57 @@
+import type { RouteRecordRaw } from 'vue-router';
+
+import { VBEN_DOC_URL, VBEN_GITHUB_URL, VBEN_LOGO_URL } from '@vben/constants';
+
+import { BasicLayout, IFrameView } from '#/layouts';
+import { $t } from '#/locales';
+
+const routes: RouteRecordRaw[] = [
+ {
+ component: BasicLayout,
+ meta: {
+ badgeType: 'dot',
+ badgeVariants: 'destructive',
+ icon: VBEN_LOGO_URL,
+ order: 9999,
+ title: $t('page.vben.title'),
+ },
+ name: 'VbenProject',
+ path: '/vben-admin',
+ children: [
+ {
+ name: 'VbenAbout',
+ path: '/vben-admin/about',
+ component: () => import('#/views/_core/vben/about/index.vue'),
+ meta: {
+ badgeType: 'dot',
+ badgeVariants: 'destructive',
+ icon: 'lucide:copyright',
+ title: $t('page.vben.about'),
+ },
+ },
+ {
+ name: 'VbenDocument',
+ path: '/vben-admin/document',
+ component: IFrameView,
+ meta: {
+ icon: 'lucide:book-open-text',
+ iframeSrc: VBEN_DOC_URL,
+ keepAlive: true,
+ title: $t('page.vben.document'),
+ },
+ },
+ {
+ name: 'VbenGithub',
+ path: '/vben-admin/github',
+ component: IFrameView,
+ meta: {
+ icon: 'mdi:github',
+ link: VBEN_GITHUB_URL,
+ title: 'Github',
+ },
+ },
+ ],
+ },
+];
+
+export default routes;
diff --git a/apps/web-naive/src/store/auth.ts b/apps/web-naive/src/store/auth.ts
new file mode 100644
index 00000000..9ad87257
--- /dev/null
+++ b/apps/web-naive/src/store/auth.ts
@@ -0,0 +1,111 @@
+import type { LoginAndRegisterParams } from '@vben/common-ui';
+import type { UserInfo } from '@vben/types';
+
+import { ref } from 'vue';
+import { useRouter } from 'vue-router';
+
+import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants';
+import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores';
+
+import { defineStore } from 'pinia';
+
+import { getAccessCodes, getUserInfo, login } from '#/api';
+import { $t } from '#/locales';
+import { notification } from '#/naive';
+
+export const useAuthStore = defineStore('auth', () => {
+ const accessStore = useAccessStore();
+ const userStore = useUserStore();
+ const router = useRouter();
+
+ const loginLoading = ref(false);
+
+ /**
+ * 异步处理登录操作
+ * Asynchronously handle the login process
+ * @param params 登录表单数据
+ */
+ async function authLogin(
+ params: LoginAndRegisterParams,
+ onSuccess?: () => Promise | void,
+ ) {
+ // 异步处理用户登录操作并获取 accessToken
+ let userInfo: null | UserInfo = null;
+ try {
+ loginLoading.value = true;
+ const { accessToken, refreshToken } = await login(params);
+
+ // 如果成功获取到 accessToken
+ if (accessToken) {
+ // 将 accessToken 存储到 accessStore 中
+ accessStore.setAccessToken(accessToken);
+ accessStore.setRefreshToken(refreshToken);
+
+ // 获取用户信息并存储到 accessStore 中
+ const [fetchUserInfoResult, accessCodes] = await Promise.all([
+ fetchUserInfo(),
+ getAccessCodes(),
+ ]);
+
+ userInfo = fetchUserInfoResult;
+
+ userStore.setUserInfo(userInfo);
+ accessStore.setAccessCodes(accessCodes);
+
+ if (accessStore.loginExpired) {
+ accessStore.setLoginExpired(false);
+ } else {
+ onSuccess
+ ? await onSuccess?.()
+ : await router.push(userInfo.homePath || DEFAULT_HOME_PATH);
+ }
+
+ if (userInfo?.realName) {
+ notification.success({
+ content: $t('authentication.loginSuccess'),
+ description: `${$t('authentication.loginSuccessDesc')}:${userInfo?.realName}`,
+ duration: 3000,
+ });
+ }
+ }
+ } finally {
+ loginLoading.value = false;
+ }
+
+ return {
+ userInfo,
+ };
+ }
+
+ async function logout() {
+ resetAllStores();
+ accessStore.setLoginExpired(false);
+
+ // 回登陆页带上当前路由地址
+ await router.replace({
+ path: LOGIN_PATH,
+ query: {
+ redirect: encodeURIComponent(router.currentRoute.value.fullPath),
+ },
+ });
+ }
+
+ async function fetchUserInfo() {
+ let userInfo: null | UserInfo = null;
+ userInfo = await getUserInfo();
+ userStore.setUserInfo(userInfo);
+ return userInfo;
+ }
+
+ function $reset() {
+ loginLoading.value = false;
+ }
+
+ return {
+ $reset,
+ authLogin,
+ fetchUserInfo,
+ loginLoading,
+ logout,
+ };
+});
diff --git a/apps/web-naive/src/store/index.ts b/apps/web-naive/src/store/index.ts
new file mode 100644
index 00000000..269586ee
--- /dev/null
+++ b/apps/web-naive/src/store/index.ts
@@ -0,0 +1 @@
+export * from './auth';
diff --git a/apps/web-naive/src/views/_core/README.md b/apps/web-naive/src/views/_core/README.md
new file mode 100644
index 00000000..8248afe6
--- /dev/null
+++ b/apps/web-naive/src/views/_core/README.md
@@ -0,0 +1,3 @@
+# \_core
+
+此目录包含应用程序正常运行所需的基本视图。这些视图是应用程序布局中使用的视图。
diff --git a/apps/web-naive/src/views/_core/authentication/code-login.vue b/apps/web-naive/src/views/_core/authentication/code-login.vue
new file mode 100644
index 00000000..36cf50ec
--- /dev/null
+++ b/apps/web-naive/src/views/_core/authentication/code-login.vue
@@ -0,0 +1,30 @@
+
+
+
+
+
diff --git a/apps/web-naive/src/views/_core/authentication/forget-password.vue b/apps/web-naive/src/views/_core/authentication/forget-password.vue
new file mode 100644
index 00000000..74ccc27e
--- /dev/null
+++ b/apps/web-naive/src/views/_core/authentication/forget-password.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
diff --git a/apps/web-naive/src/views/_core/authentication/login.vue b/apps/web-naive/src/views/_core/authentication/login.vue
new file mode 100644
index 00000000..3bcdd950
--- /dev/null
+++ b/apps/web-naive/src/views/_core/authentication/login.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
diff --git a/apps/web-naive/src/views/_core/authentication/qrcode-login.vue b/apps/web-naive/src/views/_core/authentication/qrcode-login.vue
new file mode 100644
index 00000000..23f5f2da
--- /dev/null
+++ b/apps/web-naive/src/views/_core/authentication/qrcode-login.vue
@@ -0,0 +1,10 @@
+
+
+
+
+
diff --git a/apps/web-naive/src/views/_core/authentication/register.vue b/apps/web-naive/src/views/_core/authentication/register.vue
new file mode 100644
index 00000000..f6b227d9
--- /dev/null
+++ b/apps/web-naive/src/views/_core/authentication/register.vue
@@ -0,0 +1,25 @@
+
+
+
+
+
diff --git a/apps/web-naive/src/views/_core/fallback/coming-soon.vue b/apps/web-naive/src/views/_core/fallback/coming-soon.vue
new file mode 100644
index 00000000..f394930f
--- /dev/null
+++ b/apps/web-naive/src/views/_core/fallback/coming-soon.vue
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/apps/web-naive/src/views/_core/fallback/forbidden.vue b/apps/web-naive/src/views/_core/fallback/forbidden.vue
new file mode 100644
index 00000000..8ea65fed
--- /dev/null
+++ b/apps/web-naive/src/views/_core/fallback/forbidden.vue
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/apps/web-naive/src/views/_core/fallback/internal-error.vue b/apps/web-naive/src/views/_core/fallback/internal-error.vue
new file mode 100644
index 00000000..819a47d5
--- /dev/null
+++ b/apps/web-naive/src/views/_core/fallback/internal-error.vue
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/apps/web-naive/src/views/_core/fallback/not-found.vue b/apps/web-naive/src/views/_core/fallback/not-found.vue
new file mode 100644
index 00000000..4d178e9c
--- /dev/null
+++ b/apps/web-naive/src/views/_core/fallback/not-found.vue
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/apps/web-naive/src/views/_core/fallback/offline.vue b/apps/web-naive/src/views/_core/fallback/offline.vue
new file mode 100644
index 00000000..5de4a88d
--- /dev/null
+++ b/apps/web-naive/src/views/_core/fallback/offline.vue
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/apps/web-naive/src/views/_core/vben/about/index.vue b/apps/web-naive/src/views/_core/vben/about/index.vue
new file mode 100644
index 00000000..0ee52433
--- /dev/null
+++ b/apps/web-naive/src/views/_core/vben/about/index.vue
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/apps/web-naive/src/views/dashboard/analytics/analytics-trends.vue b/apps/web-naive/src/views/dashboard/analytics/analytics-trends.vue
new file mode 100644
index 00000000..1bef4d4e
--- /dev/null
+++ b/apps/web-naive/src/views/dashboard/analytics/analytics-trends.vue
@@ -0,0 +1,78 @@
+
+
+
+
+
diff --git a/apps/web-naive/src/views/dashboard/analytics/analytics-visits-data.vue b/apps/web-naive/src/views/dashboard/analytics/analytics-visits-data.vue
new file mode 100644
index 00000000..f03907d0
--- /dev/null
+++ b/apps/web-naive/src/views/dashboard/analytics/analytics-visits-data.vue
@@ -0,0 +1,80 @@
+
+
+
+
+
diff --git a/apps/web-naive/src/views/dashboard/analytics/analytics-visits-sales.vue b/apps/web-naive/src/views/dashboard/analytics/analytics-visits-sales.vue
new file mode 100644
index 00000000..0529a3b0
--- /dev/null
+++ b/apps/web-naive/src/views/dashboard/analytics/analytics-visits-sales.vue
@@ -0,0 +1,44 @@
+
+
+
+
+
diff --git a/apps/web-naive/src/views/dashboard/analytics/analytics-visits-source.vue b/apps/web-naive/src/views/dashboard/analytics/analytics-visits-source.vue
new file mode 100644
index 00000000..99292bf9
--- /dev/null
+++ b/apps/web-naive/src/views/dashboard/analytics/analytics-visits-source.vue
@@ -0,0 +1,63 @@
+
+
+
+
+
diff --git a/apps/web-naive/src/views/dashboard/analytics/analytics-visits.vue b/apps/web-naive/src/views/dashboard/analytics/analytics-visits.vue
new file mode 100644
index 00000000..4dfc163f
--- /dev/null
+++ b/apps/web-naive/src/views/dashboard/analytics/analytics-visits.vue
@@ -0,0 +1,53 @@
+
+
+
+
+
diff --git a/apps/web-naive/src/views/dashboard/analytics/index.vue b/apps/web-naive/src/views/dashboard/analytics/index.vue
new file mode 100644
index 00000000..00b34df1
--- /dev/null
+++ b/apps/web-naive/src/views/dashboard/analytics/index.vue
@@ -0,0 +1,90 @@
+
+
+
+
+
diff --git a/apps/web-naive/src/views/dashboard/workspace/index.vue b/apps/web-naive/src/views/dashboard/workspace/index.vue
new file mode 100644
index 00000000..c8ae0273
--- /dev/null
+++ b/apps/web-naive/src/views/dashboard/workspace/index.vue
@@ -0,0 +1,225 @@
+
+
+
+
+
+
+ 早安, {{ userStore.userInfo?.realName }}, 开始您一天的工作吧!
+
+ 今日晴,20℃ - 32℃!
+
+
+
+
+
diff --git a/apps/web-naive/src/views/demos/naive/index.vue b/apps/web-naive/src/views/demos/naive/index.vue
new file mode 100644
index 00000000..26b4ace7
--- /dev/null
+++ b/apps/web-naive/src/views/demos/naive/index.vue
@@ -0,0 +1,93 @@
+
+
+
+
+
+
naive组件使用演示
+
支持多语言,主题功能集成切换等
+
+
+
+
+ 按钮
+
+
+
+ Default
+ Tertiary
+ Primary
+ Info
+ Success
+ Warning
+ Error
+
+
+
+
+
+
+
+ 信息 Message
+
+
+ 错误
+ 警告
+ 成功
+ 加载中
+
+
+
+
+
+ 通知 Notification
+
+
+ 错误
+ 警告
+ 成功
+ 加载中
+
+
+
+
diff --git a/apps/web-naive/tailwind.config.mjs b/apps/web-naive/tailwind.config.mjs
new file mode 100644
index 00000000..f17f556f
--- /dev/null
+++ b/apps/web-naive/tailwind.config.mjs
@@ -0,0 +1 @@
+export { default } from '@vben/tailwind-config';
diff --git a/apps/web-naive/tsconfig.json b/apps/web-naive/tsconfig.json
new file mode 100644
index 00000000..02c287fe
--- /dev/null
+++ b/apps/web-naive/tsconfig.json
@@ -0,0 +1,12 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "extends": "@vben/tsconfig/web-app.json",
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "#/*": ["./src/*"]
+ }
+ },
+ "references": [{ "path": "./tsconfig.node.json" }],
+ "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
+}
diff --git a/apps/web-naive/tsconfig.node.json b/apps/web-naive/tsconfig.node.json
new file mode 100644
index 00000000..c2f0d86c
--- /dev/null
+++ b/apps/web-naive/tsconfig.node.json
@@ -0,0 +1,10 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "extends": "@vben/tsconfig/node.json",
+ "compilerOptions": {
+ "composite": true,
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
+ "noEmit": false
+ },
+ "include": ["vite.config.mts"]
+}
diff --git a/apps/web-naive/vite.config.mts b/apps/web-naive/vite.config.mts
new file mode 100644
index 00000000..b6360f1d
--- /dev/null
+++ b/apps/web-naive/vite.config.mts
@@ -0,0 +1,20 @@
+import { defineConfig } from '@vben/vite-config';
+
+export default defineConfig(async () => {
+ return {
+ application: {},
+ vite: {
+ server: {
+ proxy: {
+ '/api': {
+ changeOrigin: true,
+ rewrite: (path) => path.replace(/^\/api/, ''),
+ // mock代理目标地址
+ target: 'http://localhost:5320/api',
+ ws: true,
+ },
+ },
+ },
+ },
+ };
+});
diff --git a/internal/vite-config/package.json b/internal/vite-config/package.json
index 6b01b3f4..b4cf6e5f 100644
--- a/internal/vite-config/package.json
+++ b/internal/vite-config/package.json
@@ -32,6 +32,7 @@
"cheerio": "1.0.0-rc.12",
"html-minifier-terser": "^7.2.0",
"nitropack": "^2.9.7",
+ "portfinder": "^1.0.32",
"resolve.exports": "^2.0.2",
"vite-plugin-lib-inject-css": "^2.1.1",
"vite-plugin-pwa": "^0.20.1",
diff --git a/internal/vite-config/src/plugins/nitor-mock.ts b/internal/vite-config/src/plugins/nitor-mock.ts
index 0236fae6..69c6454b 100644
--- a/internal/vite-config/src/plugins/nitor-mock.ts
+++ b/internal/vite-config/src/plugins/nitor-mock.ts
@@ -5,6 +5,7 @@ import type { NitroMockPluginOptions } from '../typing';
import { colors, consola, getPackage } from '@vben/node-utils';
import { build, createDevServer, createNitro, prepare } from 'nitropack';
+import portfinder from 'portfinder';
const hmrKeyRe = /^runtimeConfig\.|routeRules\./;
@@ -75,7 +76,13 @@ async function runNitroServer(rootDir: string, port: number, verbose: boolean) {
},
);
nitro.hooks.hookOnce('restart', reload);
+
const server = createDevServer(nitro);
+ // 端口已经存在
+ const availablePort = await portfinder.getPortPromise({ port });
+ if (availablePort !== port) {
+ return;
+ }
await server.listen(port, { showURL: false });
await prepare(nitro);
await build(nitro);
diff --git a/package.json b/package.json
index 4be35413..d31aeb40 100644
--- a/package.json
+++ b/package.json
@@ -38,6 +38,8 @@
"clean": "vsh clean",
"commit": "czg",
"dev": "cross-env turbo run dev",
+ "dev:antd": "pnpm -F @vben/web-antd",
+ "dev:naive": "pnpm -F @vben/web-naive",
"dev:docs": "pnpm -F @vben/website run docs:dev",
"format": "vsh lint --format",
"lint": "vsh lint",
diff --git a/packages/@core/preferences/src/config.ts b/packages/@core/preferences/src/config.ts
index 248d7cc4..427d7b93 100644
--- a/packages/@core/preferences/src/config.ts
+++ b/packages/@core/preferences/src/config.ts
@@ -18,7 +18,7 @@ const defaultPreferences: Preferences = {
layout: 'sidebar-nav',
locale: 'zh-CN',
loginExpiredMode: 'modal',
- name: 'Vben Admin',
+ name: 'Vben Admin Naive',
watermark: false,
},
breadcrumb: {
diff --git a/packages/@core/ui-kit/tabs-ui/src/tabs-view.vue b/packages/@core/ui-kit/tabs-ui/src/tabs-view.vue
index 9cb0306c..d68e9550 100644
--- a/packages/@core/ui-kit/tabs-ui/src/tabs-view.vue
+++ b/packages/@core/ui-kit/tabs-ui/src/tabs-view.vue
@@ -2,7 +2,7 @@
import type { Sortable } from '@vben-core/composables';
import type { TabDefinition } from '@vben-core/typings';
-import { nextTick, onMounted, onUnmounted, ref } from 'vue';
+import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
import { useForwardPropsEmits, useSortable } from '@vben-core/composables';
@@ -105,6 +105,14 @@ async function initTabsSortable() {
onMounted(initTabsSortable);
+watch(
+ () => props.styleType,
+ () => {
+ sortableInstance.value?.destroy();
+ initTabsSortable();
+ },
+);
+
onUnmounted(() => {
sortableInstance.value?.destroy();
});
diff --git a/packages/effects/hooks/src/use-design-tokens.ts b/packages/effects/hooks/src/use-design-tokens.ts
index 3fc33da3..8e6bb6f6 100644
--- a/packages/effects/hooks/src/use-design-tokens.ts
+++ b/packages/effects/hooks/src/use-design-tokens.ts
@@ -2,10 +2,14 @@ import { reactive, watch } from 'vue';
import { preferences } from '@vben/preferences';
-export function useDesignTokens() {
+/**
+ * 用于适配各个框架的设计系统
+ */
+
+export function useAntdDesignTokens() {
const rootStyles = getComputedStyle(document.documentElement);
- const antDesignTokens = reactive({
+ const tokens = reactive({
borderRadius: '' as any,
colorBgBase: '',
colorBgContainer: '',
@@ -29,23 +33,124 @@ export function useDesignTokens() {
watch(
() => preferences.theme,
() => {
- antDesignTokens.colorPrimary = getCssVariableValue('--primary');
- antDesignTokens.colorError = getCssVariableValue('--destructive');
- antDesignTokens.colorWarning = getCssVariableValue('--warning');
- antDesignTokens.colorSuccess = getCssVariableValue('--success');
- antDesignTokens.colorBgBase = getCssVariableValue('--background');
- antDesignTokens.colorBgLayout = getCssVariableValue('--background-deep');
- antDesignTokens.colorBgMask = getCssVariableValue('--overlay');
- antDesignTokens.colorBorder = getCssVariableValue('--border');
- antDesignTokens.colorTextBase = getCssVariableValue('--foreground');
- antDesignTokens.colorBgElevated = getCssVariableValue('--popover');
- antDesignTokens.colorBgContainer = getCssVariableValue('--card');
- antDesignTokens.borderRadius = getCssVariableValue('--radius', false);
+ tokens.colorPrimary = getCssVariableValue('--primary');
+
+ tokens.colorError = getCssVariableValue('--destructive');
+
+ tokens.colorWarning = getCssVariableValue('--warning');
+
+ tokens.colorSuccess = getCssVariableValue('--success');
+
+ tokens.colorTextBase = getCssVariableValue('--foreground');
+
+ getCssVariableValue('--primary-foreground');
+
+ tokens.colorBorder = getCssVariableValue('--border');
+
+ tokens.colorBgElevated = getCssVariableValue('--popover');
+
+ tokens.colorBgContainer = getCssVariableValue('--card');
+
+ tokens.colorBgBase = getCssVariableValue('--background');
+
+ tokens.borderRadius = getCssVariableValue('--radius', false);
+
+ tokens.colorBgLayout = getCssVariableValue('--background-deep');
+ tokens.colorBgMask = getCssVariableValue('--overlay');
},
{ immediate: true },
);
return {
- antDesignTokens,
+ tokens,
+ };
+}
+
+export function useNaiveDesignTokens() {
+ const rootStyles = getComputedStyle(document.documentElement);
+
+ const commonTokens = reactive({
+ baseColor: '',
+ bodyColor: '',
+ borderColor: '',
+ borderRadius: '',
+ cardColor: '',
+ dividerColor: '',
+ errorColor: '',
+ errorColorHover: '',
+ errorColorPressed: '',
+ errorColorSuppl: '',
+ invertedColor: '',
+ modalColor: '',
+ popoverColor: '',
+ primaryColor: '',
+ primaryColorHover: '',
+ primaryColorPressed: '',
+ primaryColorSuppl: '',
+ successColor: '',
+ successColorHover: '',
+ successColorPressed: '',
+ successColorSuppl: '',
+ tableColor: '',
+ textColorBase: '',
+ warningColor: '',
+ warningColorHover: '',
+ warningColorPressed: '',
+ warningColorSuppl: '',
+ });
+
+ const getCssVariableValue = (variable: string, isColor: boolean = true) => {
+ const value = rootStyles.getPropertyValue(variable);
+ return isColor ? `hsl(${value})` : value;
+ };
+
+ watch(
+ () => preferences.theme,
+ () => {
+ commonTokens.primaryColor = getCssVariableValue('--primary');
+ commonTokens.primaryColorHover = getCssVariableValue('--primary-600');
+ commonTokens.primaryColorPressed = getCssVariableValue('--primary-700');
+ commonTokens.primaryColorSuppl = getCssVariableValue('--primary-800');
+
+ commonTokens.errorColor = getCssVariableValue('--destructive');
+ commonTokens.errorColorHover = getCssVariableValue('--destructive-600');
+ commonTokens.errorColorPressed = getCssVariableValue('--destructive-700');
+ commonTokens.errorColorSuppl = getCssVariableValue('--destructive-800');
+
+ commonTokens.warningColor = getCssVariableValue('--warning');
+ commonTokens.warningColorHover = getCssVariableValue('--warning-600');
+ commonTokens.warningColorPressed = getCssVariableValue('--warning-700');
+ commonTokens.warningColorSuppl = getCssVariableValue('--warning-800');
+
+ commonTokens.successColor = getCssVariableValue('--success');
+ commonTokens.successColorHover = getCssVariableValue('--success-600');
+ commonTokens.successColorPressed = getCssVariableValue('--success-700');
+ commonTokens.successColorSuppl = getCssVariableValue('--success-800');
+
+ commonTokens.textColorBase = getCssVariableValue('--foreground');
+
+ commonTokens.baseColor = getCssVariableValue('--primary-foreground');
+
+ commonTokens.dividerColor = commonTokens.borderColor =
+ getCssVariableValue('--border');
+
+ commonTokens.modalColor = commonTokens.popoverColor =
+ getCssVariableValue('--popover');
+
+ commonTokens.tableColor = commonTokens.cardColor =
+ getCssVariableValue('--card');
+
+ commonTokens.bodyColor = getCssVariableValue('--background');
+ commonTokens.invertedColor = getCssVariableValue('--background-deep');
+
+ commonTokens.borderRadius = getCssVariableValue('--radius', false);
+
+ // antDesignTokens.colorBgMask = getCssVariableValue('--overlay');
+ },
+ { immediate: true },
+ );
+
+ return {
+ commonTokens,
};
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 730654ce..bf31af0f 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -167,6 +167,66 @@ importers:
specifier: ^4.4.0
version: 4.4.0(vue@3.4.34(typescript@5.5.4))
+ apps/web-naive:
+ dependencies:
+ '@vben/access':
+ specifier: workspace:*
+ version: link:../../packages/effects/access
+ '@vben/chart-ui':
+ specifier: workspace:*
+ version: link:../../packages/effects/chart-ui
+ '@vben/common-ui':
+ specifier: workspace:*
+ version: link:../../packages/effects/common-ui
+ '@vben/constants':
+ specifier: workspace:*
+ version: link:../../packages/constants
+ '@vben/hooks':
+ specifier: workspace:*
+ version: link:../../packages/effects/hooks
+ '@vben/icons':
+ specifier: workspace:*
+ version: link:../../packages/icons
+ '@vben/layouts':
+ specifier: workspace:*
+ version: link:../../packages/effects/layouts
+ '@vben/locales':
+ specifier: workspace:*
+ version: link:../../packages/locales
+ '@vben/preferences':
+ specifier: workspace:*
+ version: link:../../packages/preferences
+ '@vben/request':
+ specifier: workspace:*
+ version: link:../../packages/effects/request
+ '@vben/stores':
+ specifier: workspace:*
+ version: link:../../packages/stores
+ '@vben/styles':
+ specifier: workspace:*
+ version: link:../../packages/styles
+ '@vben/types':
+ specifier: workspace:*
+ version: link:../../packages/types
+ '@vben/utils':
+ specifier: workspace:*
+ version: link:../../packages/utils
+ '@vueuse/core':
+ specifier: ^10.11.0
+ version: 10.11.0(vue@3.4.34(typescript@5.5.4))
+ naive-ui:
+ specifier: ^2.39.0
+ version: 2.39.0(vue@3.4.34(typescript@5.5.4))
+ pinia:
+ specifier: 2.1.7
+ version: 2.1.7(typescript@5.5.4)(vue@3.4.34(typescript@5.5.4))
+ vue:
+ specifier: ^3.4.34
+ version: 3.4.34(typescript@5.5.4)
+ vue-router:
+ specifier: ^4.4.0
+ version: 4.4.0(vue@3.4.34(typescript@5.5.4))
+
internal/lint-configs/commitlint-config:
dependencies:
'@commitlint/cli':
@@ -430,6 +490,9 @@ importers:
nitropack:
specifier: ^2.9.7
version: 2.9.7(encoding@0.1.13)
+ portfinder:
+ specifier: ^1.0.32
+ version: 1.0.32
resolve.exports:
specifier: ^2.0.2
version: 2.0.2
@@ -1070,36 +1133,42 @@ packages:
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@ast-grep/napi-linux-arm64-gnu@0.22.6':
resolution: {integrity: sha512-9PAqNJlAQfFm1RW0DVCM/S4gFHdppxUTWacB3qEeJZXgdLnoH0KGQa4z3Xo559SPYDKZy0VnY02mZ3XJ+v6/Vw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@ast-grep/napi-linux-x64-gnu@0.21.4':
resolution: {integrity: sha512-U7jl8RGpxKV+pjFstY0y5qD+D+wm9dXNO7NBbIOnETgTMizTFiUuQWT7SOlIklhcxxuXqWzfwhNN1qwI0tGNWw==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@ast-grep/napi-linux-x64-gnu@0.22.6':
resolution: {integrity: sha512-nZf+gxXVrZqvP1LN6HwzOMA4brF3umBXfMequQzv8S6HeJ4c34P23F0Tw8mHtQpVYP9PQWJUvt3LJQ8Xvd5Hiw==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@ast-grep/napi-linux-x64-musl@0.21.4':
resolution: {integrity: sha512-SOGR93kGomRR+Vh87+jXI3pJLR+J+dekCI8a4S22kGX9iAen8/+Ew++lFouDueKLyszmmhCrIk1WnJvYPuSFBw==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@ast-grep/napi-linux-x64-musl@0.22.6':
resolution: {integrity: sha512-gcJeBMgJQf2pZZo0lgH0Vg4ycyujM7Am8VlomXhavC/dPpkddA1tiHSIC4fCNneLU1EqHITy3ALSmM4GLdsjBw==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@ast-grep/napi-win32-arm64-msvc@0.21.4':
resolution: {integrity: sha512-ciGaTbkPjbCGqUyLwIPvcNeftNXjSG3cXE+5NiLThRbDhh2yUOE8YJkElUQcu0xQCdSlXnb4l/imEED/65jGfw==}
@@ -2094,6 +2163,16 @@ packages:
resolution: {integrity: sha512-+MEFtLb/VJK5WEwmtLCqfghkDBnPNK5XdUNt24tKfwinAlf4VSMxCmplqPwRjXVIbT5C4stSUY/ZrPadEWjw8Q==}
engines: {node: '>=18.0'}
+ '@css-render/plugin-bem@0.15.14':
+ resolution: {integrity: sha512-QK513CJ7yEQxm/P3EwsI+d+ha8kSOcjGvD6SevM41neEMxdULE+18iuQK6tEChAWMOQNQPLG/Rw3Khb69r5neg==}
+ peerDependencies:
+ css-render: ~0.15.14
+
+ '@css-render/vue3-ssr@0.15.14':
+ resolution: {integrity: sha512-//8027GSbxE9n3QlD73xFY6z4ZbHbvrOVB7AO6hsmrEzGbg+h2A09HboUyDgu+xsmj7JnvJD39Irt+2D0+iV8g==}
+ peerDependencies:
+ vue: ^3.4.34
+
'@csstools/cascade-layer-name-parser@1.0.13':
resolution: {integrity: sha512-MX0yLTwtZzr82sQ0zOjqimpZbzjMaK/h2pmlrLK7DCzlmiZLYFpoO94WmN1akRVo6ll/TdpHb53vihHLUMyvng==}
engines: {node: ^14 || ^16 || >=18}
@@ -2364,6 +2443,9 @@ packages:
'@dual-bundle/import-meta-resolve@4.1.0':
resolution: {integrity: sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==}
+ '@emotion/hash@0.8.0':
+ resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==}
+
'@emotion/hash@0.9.2':
resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==}
@@ -3082,6 +3164,9 @@ packages:
'@jspm/import-map@1.1.0':
resolution: {integrity: sha512-vmk583YnMi4fmqeXbWIBiyzFu+vqVZ5VCoaa6H4xeSQy5E6JAWtmcq72OAMFTeSTqw7xxHQIJFq2OlHKdUWitQ==}
+ '@juggle/resize-observer@3.4.0':
+ resolution: {integrity: sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==}
+
'@ls-lint/ls-lint@2.2.3':
resolution: {integrity: sha512-ekM12jNm/7O2I/hsRv9HvYkRdfrHpiV1epVuI2NP+eTIcEgdIdKkKCs9KgQydu/8R5YXTov9aHdOgplmCHLupw==}
os: [darwin, linux, win32]
@@ -3186,30 +3271,35 @@ packages:
engines: {node: '>= 10.0.0'}
cpu: [arm]
os: [linux]
+ libc: [glibc]
'@parcel/watcher-linux-arm64-glibc@2.4.1':
resolution: {integrity: sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@parcel/watcher-linux-arm64-musl@2.4.1':
resolution: {integrity: sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@parcel/watcher-linux-x64-glibc@2.4.1':
resolution: {integrity: sha512-s9O3fByZ/2pyYDPoLM6zt92yu6P4E39a03zvO0qCHOTjxmt3GHRMLuRZEWhWLASTMSrrnVNWdVI/+pUElJBBBg==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@parcel/watcher-linux-x64-musl@2.4.1':
resolution: {integrity: sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@parcel/watcher-wasm@2.4.1':
resolution: {integrity: sha512-/ZR0RxqxU/xxDGzbzosMjh4W6NdYFMqq2nvo2b8SLi7rsl/4jkL8S5stIikorNkdR50oVDvqb/3JT05WM+CRRA==}
@@ -3409,91 +3499,109 @@ packages:
resolution: {integrity: sha512-2Rn36Ubxdv32NUcfm0wB1tgKqkQuft00PtM23VqLuCUR4N5jcNWDoV5iBC9jeGdgS38WK66ElncprqgMUOyomw==}
cpu: [arm]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-arm-gnueabihf@4.19.1':
resolution: {integrity: sha512-MXg1xp+e5GhZ3Vit1gGEyoC+dyQUBy2JgVQ+3hUrD9wZMkUw/ywgkpK7oZgnB6kPpGrxJ41clkPPnsknuD6M2Q==}
cpu: [arm]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-arm-musleabihf@4.19.0':
resolution: {integrity: sha512-gJuzIVdq/X1ZA2bHeCGCISe0VWqCoNT8BvkQ+BfsixXwTOndhtLUpOg0A1Fcx/+eA6ei6rMBzlOz4JzmiDw7JQ==}
cpu: [arm]
os: [linux]
+ libc: [musl]
'@rollup/rollup-linux-arm-musleabihf@4.19.1':
resolution: {integrity: sha512-DZNLwIY4ftPSRVkJEaxYkq7u2zel7aah57HESuNkUnz+3bZHxwkCUkrfS2IWC1sxK6F2QNIR0Qr/YXw7nkF3Pw==}
cpu: [arm]
os: [linux]
+ libc: [musl]
'@rollup/rollup-linux-arm64-gnu@4.19.0':
resolution: {integrity: sha512-0EkX2HYPkSADo9cfeGFoQ7R0/wTKb7q6DdwI4Yn/ULFE1wuRRCHybxpl2goQrx4c/yzK3I8OlgtBu4xvted0ug==}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-arm64-gnu@4.19.1':
resolution: {integrity: sha512-C7evongnjyxdngSDRRSQv5GvyfISizgtk9RM+z2biV5kY6S/NF/wta7K+DanmktC5DkuaJQgoKGf7KUDmA7RUw==}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-arm64-musl@4.19.0':
resolution: {integrity: sha512-GlIQRj9px52ISomIOEUq/IojLZqzkvRpdP3cLgIE1wUWaiU5Takwlzpz002q0Nxxr1y2ZgxC2obWxjr13lvxNQ==}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@rollup/rollup-linux-arm64-musl@4.19.1':
resolution: {integrity: sha512-89tFWqxfxLLHkAthAcrTs9etAoBFRduNfWdl2xUs/yLV+7XDrJ5yuXMHptNqf1Zw0UCA3cAutkAiAokYCkaPtw==}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@rollup/rollup-linux-powerpc64le-gnu@4.19.0':
resolution: {integrity: sha512-N6cFJzssruDLUOKfEKeovCKiHcdwVYOT1Hs6dovDQ61+Y9n3Ek4zXvtghPPelt6U0AH4aDGnDLb83uiJMkWYzQ==}
cpu: [ppc64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-powerpc64le-gnu@4.19.1':
resolution: {integrity: sha512-PromGeV50sq+YfaisG8W3fd+Cl6mnOOiNv2qKKqKCpiiEke2KiKVyDqG/Mb9GWKbYMHj5a01fq/qlUR28PFhCQ==}
cpu: [ppc64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-riscv64-gnu@4.19.0':
resolution: {integrity: sha512-2DnD3mkS2uuam/alF+I7M84koGwvn3ZVD7uG+LEWpyzo/bq8+kKnus2EVCkcvh6PlNB8QPNFOz6fWd5N8o1CYg==}
cpu: [riscv64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-riscv64-gnu@4.19.1':
resolution: {integrity: sha512-/1BmHYh+iz0cNCP0oHCuF8CSiNj0JOGf0jRlSo3L/FAyZyG2rGBuKpkZVH9YF+x58r1jgWxvm1aRg3DHrLDt6A==}
cpu: [riscv64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-s390x-gnu@4.19.0':
resolution: {integrity: sha512-D6pkaF7OpE7lzlTOFCB2m3Ngzu2ykw40Nka9WmKGUOTS3xcIieHe82slQlNq69sVB04ch73thKYIWz/Ian8DUA==}
cpu: [s390x]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-s390x-gnu@4.19.1':
resolution: {integrity: sha512-0cYP5rGkQWRZKy9/HtsWVStLXzCF3cCBTRI+qRL8Z+wkYlqN7zrSYm6FuY5Kd5ysS5aH0q5lVgb/WbG4jqXN1Q==}
cpu: [s390x]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-x64-gnu@4.19.0':
resolution: {integrity: sha512-HBndjQLP8OsdJNSxpNIN0einbDmRFg9+UQeZV1eiYupIRuZsDEoeGU43NQsS34Pp166DtwQOnpcbV/zQxM+rWA==}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-x64-gnu@4.19.1':
resolution: {integrity: sha512-XUXeI9eM8rMP8aGvii/aOOiMvTs7xlCosq9xCjcqI9+5hBxtjDpD+7Abm1ZhVIFE1J2h2VIg0t2DX/gjespC2Q==}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-x64-musl@4.19.0':
resolution: {integrity: sha512-HxfbvfCKJe/RMYJJn0a12eiOI9OOtAUF4G6ozrFUK95BNyoJaSiBjIOHjZskTUffUrB84IPKkFG9H9nEvJGW6A==}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@rollup/rollup-linux-x64-musl@4.19.1':
resolution: {integrity: sha512-V7cBw/cKXMfEVhpSvVZhC+iGifD6U1zJ4tbibjjN+Xi3blSXaj/rJynAkCFFQfoG6VZrAiP7uGVzL440Q6Me2Q==}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@rollup/rollup-win32-arm64-msvc@4.19.0':
resolution: {integrity: sha512-HxDMKIhmcguGTiP5TsLNolwBUK3nGGUEoV/BO9ldUBoMLBssvh4J0X8pf11i1fTV7WShWItB1bKAKjX4RQeYmg==}
@@ -3640,9 +3748,15 @@ packages:
'@types/jsonfile@6.1.4':
resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==}
+ '@types/katex@0.16.7':
+ resolution: {integrity: sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==}
+
'@types/linkify-it@5.0.0':
resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==}
+ '@types/lodash-es@4.17.12':
+ resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==}
+
'@types/lodash.clonedeep@4.5.9':
resolution: {integrity: sha512-19429mWC+FyaAhOLzsS8kZUsI+/GmBAQ0HFiCPsKGU+7pBXOQWhyrY6xNNDwUSX8SMZMJvuFVMF9O5dQOlQK9Q==}
@@ -4228,6 +4342,9 @@ packages:
async-validator@4.2.5:
resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==}
+ async@2.6.4:
+ resolution: {integrity: sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==}
+
async@3.2.5:
resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==}
@@ -4781,6 +4898,9 @@ packages:
peerDependencies:
postcss: ^8.4
+ css-render@0.15.14:
+ resolution: {integrity: sha512-9nF4PdUle+5ta4W5SyZdLCCmFd37uVimSjg1evcTqKJCyvCEEj12WKzOSBNak6r4im4J4iYXKH1OWpUV5LBYFg==}
+
css-select@4.3.0:
resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==}
@@ -4833,6 +4953,9 @@ packages:
resolution: {integrity: sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==}
engines: {node: '>=18'}
+ csstype@3.0.11:
+ resolution: {integrity: sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==}
+
csstype@3.1.3:
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
@@ -4872,6 +4995,15 @@ packages:
dataloader@1.4.0:
resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==}
+ date-fns-tz@2.0.1:
+ resolution: {integrity: sha512-fJCG3Pwx8HUoLhkepdsP7Z5RsucUi+ZBOxyM5d0ZZ6c4SdYustq0VMmOu6Wf7bli+yS/Jwp91TOCqn9jMcVrUA==}
+ peerDependencies:
+ date-fns: 2.x
+
+ date-fns@2.30.0:
+ resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==}
+ engines: {node: '>=0.11'}
+
dayjs@1.11.12:
resolution: {integrity: sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==}
@@ -5475,6 +5607,9 @@ packages:
resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
engines: {node: '>=0.8.x'}
+ evtd@0.2.4:
+ resolution: {integrity: sha512-qaeGN5bx63s/AXgQo8gj6fBkxge+OoLddLniox5qtLAEY5HSnuSlISXVPxnSae1dWblvTh4/HoMIB+mbMsvZzw==}
+
execa@8.0.1:
resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
engines: {node: '>=16.17'}
@@ -5877,6 +6012,10 @@ packages:
resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
hasBin: true
+ highlight.js@11.10.0:
+ resolution: {integrity: sha512-SYVnVFswQER+zu1laSya563s+F8VDGt7o35d4utbamowvUNLLMovFqwCLSocpZTz3MgaSRA1IbqRWZv97dtErQ==}
+ engines: {node: '>=12.0.0'}
+
homedir-polyfill@1.0.3:
resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==}
engines: {node: '>=0.10.0'}
@@ -6693,6 +6832,10 @@ packages:
mitt@3.0.1:
resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==}
+ mkdirp@0.5.6:
+ resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
+ hasBin: true
+
mkdirp@1.0.4:
resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
engines: {node: '>=10'}
@@ -6743,6 +6886,11 @@ packages:
mz@2.7.0:
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
+ naive-ui@2.39.0:
+ resolution: {integrity: sha512-5oUJzRG+rtLSH8eRU+fJvVYiQids2BxF9jp+fwGoAqHOptEINrBlgBu9uy+95RHE5FLJ7Q/z41o+qkoGnUrKxQ==}
+ peerDependencies:
+ vue: ^3.4.34
+
nanoid@3.3.7:
resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
@@ -7139,6 +7287,10 @@ packages:
resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==}
engines: {node: '>=10.13.0'}
+ portfinder@1.0.32:
+ resolution: {integrity: sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==}
+ engines: {node: '>= 0.12.0'}
+
possible-typed-array-names@1.0.0:
resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==}
engines: {node: '>= 0.4'}
@@ -7989,6 +8141,9 @@ packages:
search-insights@2.15.0:
resolution: {integrity: sha512-ch2sPCUDD4sbPQdknVl9ALSi9H7VyoeVbsxznYz6QV55jJ8CI3EtwpO1i84keN4+hF5IeHWIeGvc08530JkVXQ==}
+ seemly@0.3.8:
+ resolution: {integrity: sha512-MW8Qs6vbzo0pHmDpFSYPna+lwpZ6Zk1ancbajw/7E8TKtHdV+1DfZZD+kKJEhG/cAoB/i+LiT+5msZOqj0DwRA==}
+
semver-compare@1.0.0:
resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==}
@@ -8554,6 +8709,9 @@ packages:
resolution: {integrity: sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==}
engines: {node: '>=18'}
+ treemate@0.3.11:
+ resolution: {integrity: sha512-M8RGFoKtZ8dF+iwJfAJTOH/SM4KluKOKRJpjCMhI8bG3qB74zrFoArKZ62ll0Fr3mqkMJiQOmWYkdYgDeITYQg==}
+
ts-api-utils@1.3.0:
resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==}
engines: {node: '>=16'}
@@ -8838,6 +8996,11 @@ packages:
validate-npm-package-license@3.0.4:
resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
+ vdirs@0.1.8:
+ resolution: {integrity: sha512-H9V1zGRLQZg9b+GdMk8MXDN2Lva0zx72MPahDKc30v+DtwKjfyOSXWRIX4t2mhDubM1H09gPhWeth/BJWPHGUw==}
+ peerDependencies:
+ vue: ^3.4.34
+
vite-hot-client@0.2.3:
resolution: {integrity: sha512-rOGAV7rUlUHX89fP2p2v0A2WWvV3QMX2UYq0fRqsWSvFvev4atHWqjwGoKaZT1VTKyLGk533ecu3eyd0o59CAg==}
peerDependencies:
@@ -8971,6 +9134,11 @@ packages:
jsdom:
optional: true
+ vooks@0.2.12:
+ resolution: {integrity: sha512-iox0I3RZzxtKlcgYaStQYKEzWWGAduMmq+jS7OrNdQo1FgGfPMubGL3uGHOU9n97NIvfFDBGnpSvkWyb/NSn/Q==}
+ peerDependencies:
+ vue: ^3.4.34
+
vscode-languageserver-textdocument@1.0.11:
resolution: {integrity: sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==}
@@ -9058,6 +9226,11 @@ packages:
typescript:
optional: true
+ vueuc@0.4.58:
+ resolution: {integrity: sha512-Wnj/N8WbPRSxSt+9ji1jtDHPzda5h2OH/0sFBhvdxDRuyCZbjGg3/cKMaKqEoe+dErTexG2R+i6Q8S/Toq1MYg==}
+ peerDependencies:
+ vue: ^3.4.34
+
w3c-xmlserializer@5.0.0:
resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==}
engines: {node: '>=18'}
@@ -9561,7 +9734,7 @@ snapshots:
'@babel/traverse': 7.24.8
'@babel/types': 7.24.9
convert-source-map: 2.0.0
- debug: 4.3.5
+ debug: 4.3.6
gensync: 1.0.0-beta.2
json5: 2.2.3
semver: 6.3.1
@@ -10349,7 +10522,7 @@ snapshots:
'@babel/helper-split-export-declaration': 7.24.7
'@babel/parser': 7.24.8
'@babel/types': 7.24.9
- debug: 4.3.5
+ debug: 4.3.6
globals: 11.12.0
transitivePeerDependencies:
- supports-color
@@ -10831,6 +11004,14 @@ snapshots:
'@cspell/url@8.13.0': {}
+ '@css-render/plugin-bem@0.15.14(css-render@0.15.14)':
+ dependencies:
+ css-render: 0.15.14
+
+ '@css-render/vue3-ssr@0.15.14(vue@3.4.34(typescript@5.5.4))':
+ dependencies:
+ vue: 3.4.34(typescript@5.5.4)
+
'@csstools/cascade-layer-name-parser@1.0.13(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1)':
dependencies:
'@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1)
@@ -11097,6 +11278,8 @@ snapshots:
'@dual-bundle/import-meta-resolve@4.1.0': {}
+ '@emotion/hash@0.8.0': {}
+
'@emotion/hash@0.9.2': {}
'@emotion/unitless@0.8.1': {}
@@ -11445,7 +11628,7 @@ snapshots:
dependencies:
'@floating-ui/dom': 1.6.8
'@floating-ui/utils': 0.2.5
- vue-demi: 0.14.8(vue@3.4.34(typescript@5.5.4))
+ vue-demi: 0.14.10(vue@3.4.34(typescript@5.5.4))
transitivePeerDependencies:
- '@vue/composition-api'
- vue
@@ -11574,6 +11757,8 @@ snapshots:
'@jspm/import-map@1.1.0': {}
+ '@juggle/resize-observer@3.4.0': {}
+
'@ls-lint/ls-lint@2.2.3': {}
'@manypkg/find-root@1.1.0':
@@ -12195,8 +12380,14 @@ snapshots:
dependencies:
'@types/node': 22.0.0
+ '@types/katex@0.16.7': {}
+
'@types/linkify-it@5.0.0': {}
+ '@types/lodash-es@4.17.12':
+ dependencies:
+ '@types/lodash': 4.17.7
+
'@types/lodash.clonedeep@4.5.9':
dependencies:
'@types/lodash': 4.17.7
@@ -12326,7 +12517,7 @@ snapshots:
dependencies:
'@typescript-eslint/types': 7.17.0
'@typescript-eslint/visitor-keys': 7.17.0
- debug: 4.3.5
+ debug: 4.3.6
globby: 11.1.0
is-glob: 4.0.3
minimatch: 9.0.5
@@ -12747,13 +12938,13 @@ snapshots:
agent-base@6.0.2:
dependencies:
- debug: 4.3.5
+ debug: 4.3.6
transitivePeerDependencies:
- supports-color
agent-base@7.1.1:
dependencies:
- debug: 4.3.5
+ debug: 4.3.6
transitivePeerDependencies:
- supports-color
@@ -12952,6 +13143,10 @@ snapshots:
async-validator@4.2.5: {}
+ async@2.6.4:
+ dependencies:
+ lodash: 4.17.21
+
async@3.2.5: {}
asynckit@0.4.0: {}
@@ -13594,6 +13789,11 @@ snapshots:
dependencies:
postcss: 8.4.40
+ css-render@0.15.14:
+ dependencies:
+ '@emotion/hash': 0.8.0
+ csstype: 3.0.11
+
css-select@4.3.0:
dependencies:
boolbase: 1.0.0
@@ -13678,6 +13878,8 @@ snapshots:
dependencies:
rrweb-cssom: 0.6.0
+ csstype@3.0.11: {}
+
csstype@3.1.3: {}
cz-git@1.9.4: {}
@@ -13713,6 +13915,14 @@ snapshots:
dataloader@1.4.0: {}
+ date-fns-tz@2.0.1(date-fns@2.30.0):
+ dependencies:
+ date-fns: 2.30.0
+
+ date-fns@2.30.0:
+ dependencies:
+ '@babel/runtime': 7.24.8
+
dayjs@1.11.12: {}
db0@0.1.4: {}
@@ -14459,6 +14669,8 @@ snapshots:
events@3.3.0: {}
+ evtd@0.2.4: {}
+
execa@8.0.1:
dependencies:
cross-spawn: 7.0.3
@@ -14908,6 +15120,8 @@ snapshots:
he@1.2.0: {}
+ highlight.js@11.10.0: {}
+
homedir-polyfill@1.0.3:
dependencies:
parse-passwd: 1.0.0
@@ -14963,14 +15177,14 @@ snapshots:
dependencies:
'@tootallnate/once': 1.1.2
agent-base: 6.0.2
- debug: 4.3.5
+ debug: 4.3.6
transitivePeerDependencies:
- supports-color
http-proxy-agent@7.0.2:
dependencies:
agent-base: 7.1.1
- debug: 4.3.5
+ debug: 4.3.6
transitivePeerDependencies:
- supports-color
@@ -14979,14 +15193,14 @@ snapshots:
https-proxy-agent@5.0.1:
dependencies:
agent-base: 6.0.2
- debug: 4.3.5
+ debug: 4.3.6
transitivePeerDependencies:
- supports-color
https-proxy-agent@7.0.5:
dependencies:
agent-base: 7.1.1
- debug: 4.3.5
+ debug: 4.3.6
transitivePeerDependencies:
- supports-color
@@ -15696,6 +15910,10 @@ snapshots:
mitt@3.0.1: {}
+ mkdirp@0.5.6:
+ dependencies:
+ minimist: 1.2.8
+
mkdirp@1.0.4: {}
mkdist@1.5.4(sass@1.77.8)(typescript@5.5.4)(vue-tsc@2.0.29(typescript@5.5.4)):
@@ -15751,6 +15969,29 @@ snapshots:
object-assign: 4.1.1
thenify-all: 1.6.0
+ naive-ui@2.39.0(vue@3.4.34(typescript@5.5.4)):
+ dependencies:
+ '@css-render/plugin-bem': 0.15.14(css-render@0.15.14)
+ '@css-render/vue3-ssr': 0.15.14(vue@3.4.34(typescript@5.5.4))
+ '@types/katex': 0.16.7
+ '@types/lodash': 4.17.7
+ '@types/lodash-es': 4.17.12
+ async-validator: 4.2.5
+ css-render: 0.15.14
+ csstype: 3.1.3
+ date-fns: 2.30.0
+ date-fns-tz: 2.0.1(date-fns@2.30.0)
+ evtd: 0.2.4
+ highlight.js: 11.10.0
+ lodash: 4.17.21
+ lodash-es: 4.17.21
+ seemly: 0.3.8
+ treemate: 0.3.11
+ vdirs: 0.1.8(vue@3.4.34(typescript@5.5.4))
+ vooks: 0.2.12(vue@3.4.34(typescript@5.5.4))
+ vue: 3.4.34(typescript@5.5.4)
+ vueuc: 0.4.58(vue@3.4.34(typescript@5.5.4))
+
nanoid@3.3.7: {}
nanoid@5.0.7: {}
@@ -16192,6 +16433,14 @@ snapshots:
pngjs@5.0.0: {}
+ portfinder@1.0.32:
+ dependencies:
+ async: 2.6.4
+ debug: 3.2.7
+ mkdirp: 0.5.6
+ transitivePeerDependencies:
+ - supports-color
+
possible-typed-array-names@1.0.0: {}
postcss-antd-fixes@0.2.0(postcss@8.4.40):
@@ -17061,6 +17310,8 @@ snapshots:
search-insights@2.15.0: {}
+ seemly@0.3.8: {}
+
semver-compare@1.0.0: {}
semver-diff@4.0.0:
@@ -17206,7 +17457,7 @@ snapshots:
socks-proxy-agent@5.0.1:
dependencies:
agent-base: 6.0.2
- debug: 4.3.5
+ debug: 4.3.6
socks: 2.8.3
transitivePeerDependencies:
- supports-color
@@ -17711,6 +17962,8 @@ snapshots:
dependencies:
punycode: 2.3.1
+ treemate@0.3.11: {}
+
ts-api-utils@1.3.0(typescript@5.5.4):
dependencies:
typescript: 5.5.4
@@ -18020,6 +18273,11 @@ snapshots:
spdx-correct: 3.2.0
spdx-expression-parse: 3.0.1
+ vdirs@0.1.8(vue@3.4.34(typescript@5.5.4)):
+ dependencies:
+ evtd: 0.2.4
+ vue: 3.4.34(typescript@5.5.4)
+
vite-hot-client@0.2.3(vite@5.3.5(@types/node@22.0.0)(sass@1.77.8)(terser@5.31.3)):
dependencies:
vite: 5.3.5(@types/node@22.0.0)(sass@1.77.8)(terser@5.31.3)
@@ -18027,7 +18285,7 @@ snapshots:
vite-node@2.0.4(@types/node@22.0.0)(sass@1.77.8)(terser@5.31.3):
dependencies:
cac: 6.7.14
- debug: 4.3.5
+ debug: 4.3.6
pathe: 1.1.2
tinyrainbow: 1.2.0
vite: 5.3.5(@types/node@22.0.0)(sass@1.77.8)(terser@5.31.3)
@@ -18090,7 +18348,7 @@ snapshots:
dependencies:
'@antfu/utils': 0.7.10
'@rollup/pluginutils': 5.1.0(rollup@4.19.1)
- debug: 4.3.5
+ debug: 4.3.6
error-stack-parser-es: 0.1.5
fs-extra: 11.2.0
open: 10.1.0
@@ -18242,6 +18500,11 @@ snapshots:
- supports-color
- terser
+ vooks@0.2.12(vue@3.4.34(typescript@5.5.4)):
+ dependencies:
+ evtd: 0.2.4
+ vue: 3.4.34(typescript@5.5.4)
+
vscode-languageserver-textdocument@1.0.11: {}
vscode-uri@3.0.8: {}
@@ -18320,6 +18583,17 @@ snapshots:
optionalDependencies:
typescript: 5.5.4
+ vueuc@0.4.58(vue@3.4.34(typescript@5.5.4)):
+ dependencies:
+ '@css-render/vue3-ssr': 0.15.14(vue@3.4.34(typescript@5.5.4))
+ '@juggle/resize-observer': 3.4.0
+ css-render: 0.15.14
+ evtd: 0.2.4
+ seemly: 0.3.8
+ vdirs: 0.1.8(vue@3.4.34(typescript@5.5.4))
+ vooks: 0.2.12(vue@3.4.34(typescript@5.5.4))
+ vue: 3.4.34(typescript@5.5.4)
+
w3c-xmlserializer@5.0.0:
dependencies:
xml-name-validator: 5.0.0
diff --git a/vben-admin.code-workspace b/vben-admin.code-workspace
index dd535275..d2d6592a 100644
--- a/vben-admin.code-workspace
+++ b/vben-admin.code-workspace
@@ -8,6 +8,10 @@
"name": "@vben/web-antd",
"path": "apps/web-antd",
},
+ {
+ "name": "@vben/web-naive",
+ "path": "apps/web-naive",
+ },
{
"name": "@vben/commitlint-config",
"path": "internal/lint-configs/commitlint-config",