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 @@ + + + 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 @@ + + + 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",