From 2d543585c28d4ac52deeeb3a143b4549ffac12c6 Mon Sep 17 00:00:00 2001 From: Kirk Lin Date: Fri, 10 May 2024 03:04:26 +0800 Subject: [PATCH] feat(thin): add `Thin` Version (#29) --- apps/thin/.env | 5 + apps/thin/.env.development | 57 ++ apps/thin/.env.production | 57 ++ apps/thin/.env.test | 5 + apps/thin/autoResolver/auto-imports.d.ts | 932 ++++++++++++++++++ apps/thin/autoResolver/components.d.ts | 71 ++ apps/thin/index.html | 115 +++ apps/thin/package.json | 64 ++ apps/thin/public/favicon.ico | Bin 0 -> 67646 bytes apps/thin/src/App.vue | 21 + apps/thin/src/AppConfiguration.ts | 96 ++ apps/thin/src/apis/index.ts | 25 + apps/thin/src/apis/internal/auth.ts | 85 ++ apps/thin/src/apis/internal/dashboard.ts | 26 + apps/thin/src/apis/internal/menu.ts | 26 + apps/thin/src/component/ActionIcon/index.ts | 6 + .../component/ActionIcon/src/ActionIcon.vue | 35 + .../component/ActionIcon/src/ToolTipper.vue | 45 + apps/thin/src/component/Authority/index.ts | 4 + .../src/component/Authority/src/Authority.vue | 25 + apps/thin/src/component/Card/index.ts | 6 + apps/thin/src/component/Card/src/DataCard.vue | 50 + .../component/Card/src/DataInsightCard.vue | 64 ++ apps/thin/src/component/PageWrapper/index.ts | 4 + .../component/PageWrapper/src/PageWrapper.vue | 30 + apps/thin/src/component/SearchDialog/index.ts | 4 + .../SearchDialog/src/SearchDialog.vue | 348 +++++++ .../src/component/SearchDialog/src/types.ts | 15 + apps/thin/src/composables/index.ts | 3 + apps/thin/src/composables/setting/index.ts | 7 + .../src/composables/setting/useAppSetting.ts | 113 +++ .../src/composables/setting/useGlobSetting.ts | 7 + .../composables/setting/useHeaderSetting.ts | 53 + .../src/composables/setting/useMenuSetting.ts | 29 + .../setting/usePermissionSetting.ts | 121 +++ .../composables/setting/useThemeSetting.ts | 70 ++ .../setting/useTransitionSetting.ts | 50 + apps/thin/src/composables/useChartOption.ts | 33 + .../composables/useNaiveUIConfigProvider.ts | 22 + apps/thin/src/composables/useSearchDialog.ts | 16 + apps/thin/src/directives/permission.ts | 32 + apps/thin/src/layouts/content/index.vue | 26 + apps/thin/src/layouts/footer/index.vue | 11 + .../layouts/header/components/Breadcrumb.vue | 89 ++ .../header/components/CollapseButton.vue | 12 + .../header/components/FullScreenButton.vue | 14 + .../header/components/LocaleSwitcher.vue | 31 + .../header/components/SearchAnyWhere.vue | 70 ++ .../header/components/UserInfoButton.vue | 66 ++ apps/thin/src/layouts/header/index.vue | 46 + apps/thin/src/layouts/index.vue | 36 + .../setting/components/SettingButton.vue | 18 + .../components/DarkMode/index.vue | 39 + .../components/SettingMenu/index.vue | 20 + .../components/SettingTransition/index.vue | 61 ++ .../components/ThemeBackup/index.vue | 42 + .../ThemeColor/components/ColorCheckbox.vue | 39 + .../components/ThemeColor/components/index.ts | 3 + .../components/ThemeColor/index.vue | 25 + .../SettingDrawer/components/index.ts | 7 + .../components/SettingDrawer/index.vue | 28 + apps/thin/src/layouts/setting/index.vue | 17 + .../src/layouts/sidebar/components/Menu.vue | 103 ++ .../sidebar/components/SidebarFooter.vue | 20 + .../sidebar/components/SidebarHeader.vue | 19 + apps/thin/src/layouts/sidebar/index.vue | 34 + apps/thin/src/layouts/transition.ts | 19 + apps/thin/src/locales/en.json | 250 +++++ apps/thin/src/locales/zh.json | 251 +++++ apps/thin/src/main.ts | 43 + .../dashboard/components/APIHealthMetrics.vue | 29 + .../dashboard/components/CardInnerIcon.vue | 49 + .../dashboard/components/DataOverview.vue | 272 +++++ .../components/PerformanceMetrics.vue | 105 ++ .../components/PopularAssistants.vue | 15 + .../components/ResponseTypeDistribution.vue | 15 + .../dashboard/components/UserAnalysis.vue | 24 + .../dashboard/components/UserAnalysisItem.vue | 127 +++ apps/thin/src/pages/dashboard/index.vue | 46 + .../pages/internal/exception/Exception.vue | 65 ++ .../pages/internal/iframe/IframeContainer.vue | 32 + .../src/pages/internal/iframe/IframePage.vue | 32 + .../internal/iframe/useFrameKeepAlive.ts | 42 + .../src/pages/internal/redirect/index.vue | 35 + .../AuthForm/components/ForgotPassword.vue | 68 ++ .../components/AuthForm/components/SignIn.vue | 95 ++ .../components/AuthForm/components/SignUp.vue | 125 +++ .../pages/login/components/AuthForm/index.vue | 99 ++ apps/thin/src/pages/login/index.vue | 84 ++ apps/thin/src/pages/login/types/index.ts | 16 + .../permission/CurrentPermissionMode.vue | 18 + .../permission/backend/ButtonPermission.vue | 102 ++ .../src/pages/permission/backend/index.vue | 43 + .../pages/permission/frontend/AuthPageA.vue | 13 + .../pages/permission/frontend/AuthPageB.vue | 13 + .../permission/frontend/ButtonPermission.vue | 84 ++ .../src/pages/permission/frontend/index.vue | 37 + apps/thin/src/pages/profile/index.vue | 77 ++ apps/thin/src/pages/result/fail.vue | 57 ++ apps/thin/src/pages/result/success.vue | 60 ++ apps/thin/src/router/constant.ts | 38 + apps/thin/src/router/guard/index.ts | 132 +++ .../thin/src/router/guard/pageLoadingGuard.ts | 60 ++ apps/thin/src/router/guard/permissionGuard.ts | 111 +++ apps/thin/src/router/guard/stateGuard.ts | 21 + apps/thin/src/router/index.ts | 44 + apps/thin/src/router/menus/index.ts | 112 +++ .../menus/modules/dashboard/dashboard.ts | 17 + apps/thin/src/router/mitt/routeChange.ts | 39 + apps/thin/src/router/routes/basic.ts | 52 + apps/thin/src/router/routes/index.ts | 37 + .../src/router/routes/modules/dashboard.ts | 30 + apps/thin/src/router/routes/modules/iframe.ts | 60 ++ .../src/router/routes/modules/permission.ts | 93 ++ .../thin/src/router/routes/modules/profile.ts | 30 + apps/thin/src/router/routes/utils.ts | 111 +++ apps/thin/src/setting/designSetting.ts | 3 + apps/thin/src/setting/encryptionSetting.ts | 15 + apps/thin/src/setting/nprogress/index.ts | 12 + apps/thin/src/setting/projectSetting.ts | 134 +++ apps/thin/src/setting/themeSetting.ts | 31 + apps/thin/src/store/index.ts | 12 + apps/thin/src/store/modules/app.ts | 91 ++ apps/thin/src/store/modules/design/index.ts | 107 ++ .../src/store/modules/design/themeUtils.ts | 159 +++ apps/thin/src/store/modules/permission.ts | 216 ++++ apps/thin/src/store/modules/user.ts | 257 +++++ apps/thin/src/store/plugin/persist.ts | 78 ++ apps/thin/src/store/subscribe/index.ts | 9 + apps/thin/src/store/subscribe/theme.ts | 93 ++ apps/thin/tsconfig.json | 23 + apps/thin/types/echarts.ts | 10 + apps/thin/types/shims-vue.d.ts | 8 + apps/thin/vercel.json | 20 + apps/thin/vite.config.ts | 3 + package.json | 2 + pnpm-lock.yaml | 124 ++- 137 files changed, 8471 insertions(+), 18 deletions(-) create mode 100644 apps/thin/.env create mode 100644 apps/thin/.env.development create mode 100644 apps/thin/.env.production create mode 100644 apps/thin/.env.test create mode 100644 apps/thin/autoResolver/auto-imports.d.ts create mode 100644 apps/thin/autoResolver/components.d.ts create mode 100644 apps/thin/index.html create mode 100644 apps/thin/package.json create mode 100644 apps/thin/public/favicon.ico create mode 100644 apps/thin/src/App.vue create mode 100644 apps/thin/src/AppConfiguration.ts create mode 100644 apps/thin/src/apis/index.ts create mode 100644 apps/thin/src/apis/internal/auth.ts create mode 100644 apps/thin/src/apis/internal/dashboard.ts create mode 100644 apps/thin/src/apis/internal/menu.ts create mode 100644 apps/thin/src/component/ActionIcon/index.ts create mode 100644 apps/thin/src/component/ActionIcon/src/ActionIcon.vue create mode 100644 apps/thin/src/component/ActionIcon/src/ToolTipper.vue create mode 100644 apps/thin/src/component/Authority/index.ts create mode 100644 apps/thin/src/component/Authority/src/Authority.vue create mode 100644 apps/thin/src/component/Card/index.ts create mode 100644 apps/thin/src/component/Card/src/DataCard.vue create mode 100644 apps/thin/src/component/Card/src/DataInsightCard.vue create mode 100644 apps/thin/src/component/PageWrapper/index.ts create mode 100644 apps/thin/src/component/PageWrapper/src/PageWrapper.vue create mode 100644 apps/thin/src/component/SearchDialog/index.ts create mode 100644 apps/thin/src/component/SearchDialog/src/SearchDialog.vue create mode 100644 apps/thin/src/component/SearchDialog/src/types.ts create mode 100644 apps/thin/src/composables/index.ts create mode 100644 apps/thin/src/composables/setting/index.ts create mode 100644 apps/thin/src/composables/setting/useAppSetting.ts create mode 100644 apps/thin/src/composables/setting/useGlobSetting.ts create mode 100644 apps/thin/src/composables/setting/useHeaderSetting.ts create mode 100644 apps/thin/src/composables/setting/useMenuSetting.ts create mode 100644 apps/thin/src/composables/setting/usePermissionSetting.ts create mode 100644 apps/thin/src/composables/setting/useThemeSetting.ts create mode 100644 apps/thin/src/composables/setting/useTransitionSetting.ts create mode 100644 apps/thin/src/composables/useChartOption.ts create mode 100644 apps/thin/src/composables/useNaiveUIConfigProvider.ts create mode 100644 apps/thin/src/composables/useSearchDialog.ts create mode 100644 apps/thin/src/directives/permission.ts create mode 100644 apps/thin/src/layouts/content/index.vue create mode 100644 apps/thin/src/layouts/footer/index.vue create mode 100644 apps/thin/src/layouts/header/components/Breadcrumb.vue create mode 100644 apps/thin/src/layouts/header/components/CollapseButton.vue create mode 100644 apps/thin/src/layouts/header/components/FullScreenButton.vue create mode 100644 apps/thin/src/layouts/header/components/LocaleSwitcher.vue create mode 100644 apps/thin/src/layouts/header/components/SearchAnyWhere.vue create mode 100644 apps/thin/src/layouts/header/components/UserInfoButton.vue create mode 100644 apps/thin/src/layouts/header/index.vue create mode 100644 apps/thin/src/layouts/index.vue create mode 100644 apps/thin/src/layouts/setting/components/SettingButton.vue create mode 100644 apps/thin/src/layouts/setting/components/SettingDrawer/components/DarkMode/index.vue create mode 100644 apps/thin/src/layouts/setting/components/SettingDrawer/components/SettingMenu/index.vue create mode 100644 apps/thin/src/layouts/setting/components/SettingDrawer/components/SettingTransition/index.vue create mode 100644 apps/thin/src/layouts/setting/components/SettingDrawer/components/ThemeBackup/index.vue create mode 100644 apps/thin/src/layouts/setting/components/SettingDrawer/components/ThemeColor/components/ColorCheckbox.vue create mode 100644 apps/thin/src/layouts/setting/components/SettingDrawer/components/ThemeColor/components/index.ts create mode 100644 apps/thin/src/layouts/setting/components/SettingDrawer/components/ThemeColor/index.vue create mode 100644 apps/thin/src/layouts/setting/components/SettingDrawer/components/index.ts create mode 100644 apps/thin/src/layouts/setting/components/SettingDrawer/index.vue create mode 100644 apps/thin/src/layouts/setting/index.vue create mode 100644 apps/thin/src/layouts/sidebar/components/Menu.vue create mode 100644 apps/thin/src/layouts/sidebar/components/SidebarFooter.vue create mode 100644 apps/thin/src/layouts/sidebar/components/SidebarHeader.vue create mode 100644 apps/thin/src/layouts/sidebar/index.vue create mode 100644 apps/thin/src/layouts/transition.ts create mode 100644 apps/thin/src/locales/en.json create mode 100644 apps/thin/src/locales/zh.json create mode 100644 apps/thin/src/main.ts create mode 100644 apps/thin/src/pages/dashboard/components/APIHealthMetrics.vue create mode 100644 apps/thin/src/pages/dashboard/components/CardInnerIcon.vue create mode 100644 apps/thin/src/pages/dashboard/components/DataOverview.vue create mode 100644 apps/thin/src/pages/dashboard/components/PerformanceMetrics.vue create mode 100644 apps/thin/src/pages/dashboard/components/PopularAssistants.vue create mode 100644 apps/thin/src/pages/dashboard/components/ResponseTypeDistribution.vue create mode 100644 apps/thin/src/pages/dashboard/components/UserAnalysis.vue create mode 100644 apps/thin/src/pages/dashboard/components/UserAnalysisItem.vue create mode 100644 apps/thin/src/pages/dashboard/index.vue create mode 100644 apps/thin/src/pages/internal/exception/Exception.vue create mode 100644 apps/thin/src/pages/internal/iframe/IframeContainer.vue create mode 100644 apps/thin/src/pages/internal/iframe/IframePage.vue create mode 100644 apps/thin/src/pages/internal/iframe/useFrameKeepAlive.ts create mode 100644 apps/thin/src/pages/internal/redirect/index.vue create mode 100644 apps/thin/src/pages/login/components/AuthForm/components/ForgotPassword.vue create mode 100644 apps/thin/src/pages/login/components/AuthForm/components/SignIn.vue create mode 100644 apps/thin/src/pages/login/components/AuthForm/components/SignUp.vue create mode 100644 apps/thin/src/pages/login/components/AuthForm/index.vue create mode 100644 apps/thin/src/pages/login/index.vue create mode 100644 apps/thin/src/pages/login/types/index.ts create mode 100644 apps/thin/src/pages/permission/CurrentPermissionMode.vue create mode 100644 apps/thin/src/pages/permission/backend/ButtonPermission.vue create mode 100644 apps/thin/src/pages/permission/backend/index.vue create mode 100644 apps/thin/src/pages/permission/frontend/AuthPageA.vue create mode 100644 apps/thin/src/pages/permission/frontend/AuthPageB.vue create mode 100644 apps/thin/src/pages/permission/frontend/ButtonPermission.vue create mode 100644 apps/thin/src/pages/permission/frontend/index.vue create mode 100644 apps/thin/src/pages/profile/index.vue create mode 100644 apps/thin/src/pages/result/fail.vue create mode 100644 apps/thin/src/pages/result/success.vue create mode 100644 apps/thin/src/router/constant.ts create mode 100644 apps/thin/src/router/guard/index.ts create mode 100644 apps/thin/src/router/guard/pageLoadingGuard.ts create mode 100644 apps/thin/src/router/guard/permissionGuard.ts create mode 100644 apps/thin/src/router/guard/stateGuard.ts create mode 100644 apps/thin/src/router/index.ts create mode 100644 apps/thin/src/router/menus/index.ts create mode 100644 apps/thin/src/router/menus/modules/dashboard/dashboard.ts create mode 100644 apps/thin/src/router/mitt/routeChange.ts create mode 100644 apps/thin/src/router/routes/basic.ts create mode 100644 apps/thin/src/router/routes/index.ts create mode 100644 apps/thin/src/router/routes/modules/dashboard.ts create mode 100644 apps/thin/src/router/routes/modules/iframe.ts create mode 100644 apps/thin/src/router/routes/modules/permission.ts create mode 100644 apps/thin/src/router/routes/modules/profile.ts create mode 100644 apps/thin/src/router/routes/utils.ts create mode 100644 apps/thin/src/setting/designSetting.ts create mode 100644 apps/thin/src/setting/encryptionSetting.ts create mode 100644 apps/thin/src/setting/nprogress/index.ts create mode 100644 apps/thin/src/setting/projectSetting.ts create mode 100644 apps/thin/src/setting/themeSetting.ts create mode 100644 apps/thin/src/store/index.ts create mode 100644 apps/thin/src/store/modules/app.ts create mode 100644 apps/thin/src/store/modules/design/index.ts create mode 100644 apps/thin/src/store/modules/design/themeUtils.ts create mode 100644 apps/thin/src/store/modules/permission.ts create mode 100644 apps/thin/src/store/modules/user.ts create mode 100644 apps/thin/src/store/plugin/persist.ts create mode 100644 apps/thin/src/store/subscribe/index.ts create mode 100644 apps/thin/src/store/subscribe/theme.ts create mode 100644 apps/thin/tsconfig.json create mode 100644 apps/thin/types/echarts.ts create mode 100644 apps/thin/types/shims-vue.d.ts create mode 100644 apps/thin/vercel.json create mode 100644 apps/thin/vite.config.ts diff --git a/apps/thin/.env b/apps/thin/.env new file mode 100644 index 00000000..12f4e270 --- /dev/null +++ b/apps/thin/.env @@ -0,0 +1,5 @@ +# The title of your application (string) +VITE_GLOB_APP_TITLE='Celeris Web Thin' + +# port +VITE_PORT=8888 diff --git a/apps/thin/.env.development b/apps/thin/.env.development new file mode 100644 index 00000000..9ab38b3e --- /dev/null +++ b/apps/thin/.env.development @@ -0,0 +1,57 @@ +# App Environment Variables + +NODE_ENV="development" + +# Whether to use mock data (true/false) +VITE_USE_MOCK=false + +# Whether to enable build analyzer (true/false) +VITE_USE_BUILD_ANALYZER=false + +# Whether to enable PWA (true/false) +VITE_USE_PWA=true + +# The public path for assets in your application +VITE_PUBLIC_PATH=/ + +# Proxy settings for your development server (array of [string, string] pairs) +VITE_PROXY=[["/api","http://localhost:8899"]] + +# Basic interface address SPA +VITE_GLOB_API_URL=/api + +# Basic interface address SSR +VITE_GLOB_API_URL_SSR=/api + +# Basic interface address prefix +VITE_GLOB_API_URL_PREFIX= + +# The title of your application (string) +VITE_GLOB_APP_TITLE="Celeris Web Thin" + +# The short name of your application (string) +VITE_GLOB_APP_SHORT_NAME="Celeris_Web_Thin" + +# Whether to use a CDN for assets (true/false) +VITE_USE_CDN=false + +# Whether to drop console.log statements (true/false) +VITE_DROP_CONSOLE=false + +# Whether to use HTTPS for your development server (true/false) +VITE_USE_HTTPS=false + +# The compression algorithm to use when building your application (gzip/brotli/none) +VITE_BUILD_COMPRESS=gzip + +# Whether to delete the original file after compressing it (true/false) +VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE=false + +# Whether to build your application in legacy mode (true/false) +VITE_LEGACY=true + +# Whether to use imagemin to optimize images during build (true/false) +VITE_USE_IMAGEMIN=true + +# Whether to generate a configuration file (true/false) +VITE_GLOB_BUILD_GENERATE_CONFIG=true diff --git a/apps/thin/.env.production b/apps/thin/.env.production new file mode 100644 index 00000000..de052e3f --- /dev/null +++ b/apps/thin/.env.production @@ -0,0 +1,57 @@ +# App Environment Variables + +NODE_ENV="production" + +# Whether to use mock data (true/false) +VITE_USE_MOCK=false + +# Whether to enable build analyzer (true/false) +VITE_USE_BUILD_ANALYZER=false + +# Whether to enable PWA (true/false) +VITE_USE_PWA=true + +# The public path for assets in your application +VITE_PUBLIC_PATH=/ + +# Proxy settings for your development server (array of [string, string] pairs) +VITE_PROXY=[["/api","https://celeris-web-api.vercel.app/"]] + +# Basic interface address SPA +VITE_GLOB_API_URL=/api + +# Basic interface address SSR +VITE_GLOB_API_URL_SSR=/api + +# Basic interface address prefix +VITE_GLOB_API_URL_PREFIX= + +# The title of your application (string) +VITE_GLOB_APP_TITLE="Celeris Web Thin" + +# The short name of your application (string) +VITE_GLOB_APP_SHORT_NAME="Celeris_Web_Thin" + +# Whether to use a CDN for assets (true/false) +VITE_USE_CDN=false + +# Whether to drop console.log statements (true/false) +VITE_DROP_CONSOLE=true + +# Whether to use HTTPS for your development server (true/false) +VITE_USE_HTTPS=false + +# The compression algorithm to use when building your application (gzip/brotli/none) +VITE_BUILD_COMPRESS=gzip + +# Whether to delete the original file after compressing it (true/false) +VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE=false + +# Whether to build your application in legacy mode (true/false) +VITE_LEGACY=true + +# Whether to use imagemin to optimize images during build (true/false) +VITE_USE_IMAGEMIN=true + +# Whether to generate a configuration file (true/false) +VITE_GLOB_BUILD_GENERATE_CONFIG=true diff --git a/apps/thin/.env.test b/apps/thin/.env.test new file mode 100644 index 00000000..3a3e07e8 --- /dev/null +++ b/apps/thin/.env.test @@ -0,0 +1,5 @@ +# 测试环境 +NODE_ENV="test" + +# 测试环境接口地址 +VITE_API_URL="/api" diff --git a/apps/thin/autoResolver/auto-imports.d.ts b/apps/thin/autoResolver/auto-imports.d.ts new file mode 100644 index 00000000..36baab41 --- /dev/null +++ b/apps/thin/autoResolver/auto-imports.d.ts @@ -0,0 +1,932 @@ +/* eslint-disable */ +/* prettier-ignore */ +// @ts-nocheck +// noinspection JSUnusedGlobalSymbols +// Generated by unplugin-auto-import +export {} +declare global { + const EffectScope: typeof import('vue')['EffectScope'] + const asyncComputed: typeof import('@vueuse/core')['asyncComputed'] + const autoResetRef: typeof import('@vueuse/core')['autoResetRef'] + const computed: typeof import('vue')['computed'] + const computedAsync: typeof import('@vueuse/core')['computedAsync'] + const computedEager: typeof import('@vueuse/core')['computedEager'] + const computedInject: typeof import('@vueuse/core')['computedInject'] + const computedWithControl: typeof import('@vueuse/core')['computedWithControl'] + const controlledComputed: typeof import('@vueuse/core')['controlledComputed'] + const controlledRef: typeof import('@vueuse/core')['controlledRef'] + const createApp: typeof import('vue')['createApp'] + const createEventHook: typeof import('@vueuse/core')['createEventHook'] + const createGlobalState: typeof import('@vueuse/core')['createGlobalState'] + const createInjectionState: typeof import('@vueuse/core')['createInjectionState'] + const createReactiveFn: typeof import('@vueuse/core')['createReactiveFn'] + const createReusableTemplate: typeof import('@vueuse/core')['createReusableTemplate'] + const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable'] + const createTemplatePromise: typeof import('@vueuse/core')['createTemplatePromise'] + const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn'] + const customRef: typeof import('vue')['customRef'] + const debouncedRef: typeof import('@vueuse/core')['debouncedRef'] + const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch'] + const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'] + const defineComponent: typeof import('vue')['defineComponent'] + const eagerComputed: typeof import('@vueuse/core')['eagerComputed'] + const effectScope: typeof import('vue')['effectScope'] + const extendRef: typeof import('@vueuse/core')['extendRef'] + const getCurrentInstance: typeof import('vue')['getCurrentInstance'] + const getCurrentScope: typeof import('vue')['getCurrentScope'] + const getPermissionMode: typeof import('../src/composables/setting/usePermissionSetting')['getPermissionMode'] + const h: typeof import('vue')['h'] + const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch'] + const inject: typeof import('vue')['inject'] + const injectLocal: typeof import('@vueuse/core')['injectLocal'] + const isBackendMode: typeof import('../src/composables/setting/usePermissionSetting')['isBackendMode'] + const isDefined: typeof import('@vueuse/core')['isDefined'] + const isProxy: typeof import('vue')['isProxy'] + const isReactive: typeof import('vue')['isReactive'] + const isReadonly: typeof import('vue')['isReadonly'] + const isRef: typeof import('vue')['isRef'] + const isRoleMode: typeof import('../src/composables/setting/usePermissionSetting')['isRoleMode'] + const isRouteMappingMode: typeof import('../src/composables/setting/usePermissionSetting')['isRouteMappingMode'] + const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable'] + const markRaw: typeof import('vue')['markRaw'] + const nextTick: typeof import('vue')['nextTick'] + const onActivated: typeof import('vue')['onActivated'] + const onBeforeMount: typeof import('vue')['onBeforeMount'] + const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave'] + const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate'] + const onBeforeUnmount: typeof import('vue')['onBeforeUnmount'] + const onBeforeUpdate: typeof import('vue')['onBeforeUpdate'] + const onClickOutside: typeof import('@vueuse/core')['onClickOutside'] + const onDeactivated: typeof import('vue')['onDeactivated'] + const onErrorCaptured: typeof import('vue')['onErrorCaptured'] + const onKeyStroke: typeof import('@vueuse/core')['onKeyStroke'] + const onLongPress: typeof import('@vueuse/core')['onLongPress'] + const onMounted: typeof import('vue')['onMounted'] + const onRenderTracked: typeof import('vue')['onRenderTracked'] + const onRenderTriggered: typeof import('vue')['onRenderTriggered'] + const onScopeDispose: typeof import('vue')['onScopeDispose'] + const onServerPrefetch: typeof import('vue')['onServerPrefetch'] + const onStartTyping: typeof import('@vueuse/core')['onStartTyping'] + const onUnmounted: typeof import('vue')['onUnmounted'] + const onUpdated: typeof import('vue')['onUpdated'] + const pausableWatch: typeof import('@vueuse/core')['pausableWatch'] + const provide: typeof import('vue')['provide'] + const provideLocal: typeof import('@vueuse/core')['provideLocal'] + const reactify: typeof import('@vueuse/core')['reactify'] + const reactifyObject: typeof import('@vueuse/core')['reactifyObject'] + const reactive: typeof import('vue')['reactive'] + const reactiveComputed: typeof import('@vueuse/core')['reactiveComputed'] + const reactiveOmit: typeof import('@vueuse/core')['reactiveOmit'] + const reactivePick: typeof import('@vueuse/core')['reactivePick'] + const readonly: typeof import('vue')['readonly'] + const ref: typeof import('vue')['ref'] + const refAutoReset: typeof import('@vueuse/core')['refAutoReset'] + const refDebounced: typeof import('@vueuse/core')['refDebounced'] + const refDefault: typeof import('@vueuse/core')['refDefault'] + const refThrottled: typeof import('@vueuse/core')['refThrottled'] + const refWithControl: typeof import('@vueuse/core')['refWithControl'] + const resolveComponent: typeof import('vue')['resolveComponent'] + const resolveRef: typeof import('@vueuse/core')['resolveRef'] + const resolveUnref: typeof import('@vueuse/core')['resolveUnref'] + const setupStore: typeof import('../src/store/index')['setupStore'] + const shallowReactive: typeof import('vue')['shallowReactive'] + const shallowReadonly: typeof import('vue')['shallowReadonly'] + const shallowRef: typeof import('vue')['shallowRef'] + const store: typeof import('../src/store/index')['store'] + const syncRef: typeof import('@vueuse/core')['syncRef'] + const syncRefs: typeof import('@vueuse/core')['syncRefs'] + const templateRef: typeof import('@vueuse/core')['templateRef'] + const throttledRef: typeof import('@vueuse/core')['throttledRef'] + const throttledWatch: typeof import('@vueuse/core')['throttledWatch'] + const toRaw: typeof import('vue')['toRaw'] + const toReactive: typeof import('@vueuse/core')['toReactive'] + const toRef: typeof import('vue')['toRef'] + const toRefs: typeof import('vue')['toRefs'] + const toValue: typeof import('vue')['toValue'] + const toggleDark: typeof import('../src/composables/dark')['toggleDark'] + const triggerRef: typeof import('vue')['triggerRef'] + const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount'] + const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount'] + const tryOnMounted: typeof import('@vueuse/core')['tryOnMounted'] + const tryOnScopeDispose: typeof import('@vueuse/core')['tryOnScopeDispose'] + const tryOnUnmounted: typeof import('@vueuse/core')['tryOnUnmounted'] + const unref: typeof import('vue')['unref'] + const unrefElement: typeof import('@vueuse/core')['unrefElement'] + const until: typeof import('@vueuse/core')['until'] + const useActiveElement: typeof import('@vueuse/core')['useActiveElement'] + const useAnimate: typeof import('@vueuse/core')['useAnimate'] + const useAppPermission: typeof import('../src/composables/setting/usePermissionSetting')['useAppPermission'] + const useAppSetting: typeof import('../src/composables/setting/useAppSetting')['useAppSetting'] + const useArrayDifference: typeof import('@vueuse/core')['useArrayDifference'] + const useArrayEvery: typeof import('@vueuse/core')['useArrayEvery'] + const useArrayFilter: typeof import('@vueuse/core')['useArrayFilter'] + const useArrayFind: typeof import('@vueuse/core')['useArrayFind'] + const useArrayFindIndex: typeof import('@vueuse/core')['useArrayFindIndex'] + const useArrayFindLast: typeof import('@vueuse/core')['useArrayFindLast'] + const useArrayIncludes: typeof import('@vueuse/core')['useArrayIncludes'] + const useArrayJoin: typeof import('@vueuse/core')['useArrayJoin'] + const useArrayMap: typeof import('@vueuse/core')['useArrayMap'] + const useArrayReduce: typeof import('@vueuse/core')['useArrayReduce'] + const useArraySome: typeof import('@vueuse/core')['useArraySome'] + const useArrayUnique: typeof import('@vueuse/core')['useArrayUnique'] + const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue'] + const useAsyncState: typeof import('@vueuse/core')['useAsyncState'] + const useAttrs: typeof import('vue')['useAttrs'] + const useBase64: typeof import('@vueuse/core')['useBase64'] + const useBattery: typeof import('@vueuse/core')['useBattery'] + const useBluetooth: typeof import('@vueuse/core')['useBluetooth'] + const useBreakpoints: typeof import('@vueuse/core')['useBreakpoints'] + const useBroadcastChannel: typeof import('@vueuse/core')['useBroadcastChannel'] + const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation'] + const useCached: typeof import('@vueuse/core')['useCached'] + const useChartOption: typeof import('../src/composables/useChartOption')['useChartOption'] + const useClipboard: typeof import('@vueuse/core')['useClipboard'] + const useClipboardItems: typeof import('@vueuse/core')['useClipboardItems'] + const useCloned: typeof import('@vueuse/core')['useCloned'] + const useColorMode: typeof import('@vueuse/core')['useColorMode'] + const useComponentRef: typeof import('@celeris/hooks')['useComponentRef'] + const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog'] + const useCounter: typeof import('@vueuse/core')['useCounter'] + const useCssModule: typeof import('vue')['useCssModule'] + const useCssVar: typeof import('@vueuse/core')['useCssVar'] + const useCssVars: typeof import('vue')['useCssVars'] + const useCurrentElement: typeof import('@vueuse/core')['useCurrentElement'] + const useCycleList: typeof import('@vueuse/core')['useCycleList'] + const useDark: typeof import('@vueuse/core')['useDark'] + const useDateFormat: typeof import('@vueuse/core')['useDateFormat'] + const useDebounce: typeof import('@vueuse/core')['useDebounce'] + const useDebounceFn: typeof import('@vueuse/core')['useDebounceFn'] + const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory'] + const useDeviceMotion: typeof import('@vueuse/core')['useDeviceMotion'] + const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation'] + const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio'] + const useDevicesList: typeof import('@vueuse/core')['useDevicesList'] + const useDialog: typeof import('@celeris/ca-components')['useDialog'] + const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia'] + const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility'] + const useDraggable: typeof import('@vueuse/core')['useDraggable'] + const useDropZone: typeof import('@vueuse/core')['useDropZone'] + const useElementBounding: typeof import('@vueuse/core')['useElementBounding'] + const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint'] + const useElementHover: typeof import('@vueuse/core')['useElementHover'] + const useElementSize: typeof import('@vueuse/core')['useElementSize'] + const useElementVisibility: typeof import('@vueuse/core')['useElementVisibility'] + const useEventBus: typeof import('@vueuse/core')['useEventBus'] + const useEventListener: typeof import('@vueuse/core')['useEventListener'] + const useEventSource: typeof import('@vueuse/core')['useEventSource'] + const useEyeDropper: typeof import('@vueuse/core')['useEyeDropper'] + const useFavicon: typeof import('@vueuse/core')['useFavicon'] + const useFetch: typeof import('@vueuse/core')['useFetch'] + const useFileDialog: typeof import('@vueuse/core')['useFileDialog'] + const useFileSystemAccess: typeof import('@vueuse/core')['useFileSystemAccess'] + const useFocus: typeof import('@vueuse/core')['useFocus'] + const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin'] + const useFps: typeof import('@vueuse/core')['useFps'] + const useFullscreen: typeof import('@vueuse/core')['useFullscreen'] + const useGamepad: typeof import('@vueuse/core')['useGamepad'] + const useGeolocation: typeof import('@vueuse/core')['useGeolocation'] + const useGlobSetting: typeof import('../src/composables/setting/useGlobSetting')['useGlobSetting'] + const useHeaderSetting: typeof import('../src/composables/setting/useHeaderSetting')['useHeaderSetting'] + const useI18n: typeof import('vue-i18n')['useI18n'] + const useIdle: typeof import('@vueuse/core')['useIdle'] + const useImage: typeof import('@vueuse/core')['useImage'] + const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll'] + const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver'] + const useInterval: typeof import('@vueuse/core')['useInterval'] + const useIntervalFn: typeof import('@vueuse/core')['useIntervalFn'] + const useKeyModifier: typeof import('@vueuse/core')['useKeyModifier'] + const useLastChanged: typeof import('@vueuse/core')['useLastChanged'] + const useLink: typeof import('vue-router')['useLink'] + const useLoading: typeof import('@celeris/hooks')['useLoading'] + const useLoadingBar: typeof import('@celeris/ca-components')['useLoadingBar'] + const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage'] + const useMagicKeys: typeof import('@vueuse/core')['useMagicKeys'] + const useManualRefHistory: typeof import('@vueuse/core')['useManualRefHistory'] + const useMediaControls: typeof import('@vueuse/core')['useMediaControls'] + const useMediaQuery: typeof import('@vueuse/core')['useMediaQuery'] + const useMemoize: typeof import('@vueuse/core')['useMemoize'] + const useMemory: typeof import('@vueuse/core')['useMemory'] + const useMenuSetting: typeof import('../src/composables/setting/useMenuSetting')['useMenuSetting'] + const useMergeState: typeof import('@celeris/hooks')['useMergeState'] + const useMessage: typeof import('@celeris/ca-components')['useMessage'] + const useMounted: typeof import('@vueuse/core')['useMounted'] + const useMouse: typeof import('@vueuse/core')['useMouse'] + const useMouseInElement: typeof import('@vueuse/core')['useMouseInElement'] + const useMousePressed: typeof import('@vueuse/core')['useMousePressed'] + const useMutationObserver: typeof import('@vueuse/core')['useMutationObserver'] + const useNaiveUIConfigProvider: typeof import('../src/composables/useNaiveUIConfigProvider')['useNaiveUIConfigProvider'] + const useNavigatorLanguage: typeof import('@vueuse/core')['useNavigatorLanguage'] + const useNetwork: typeof import('@vueuse/core')['useNetwork'] + const useNotification: typeof import('@celeris/ca-components')['useNotification'] + const useNow: typeof import('@vueuse/core')['useNow'] + const useObjectUrl: typeof import('@vueuse/core')['useObjectUrl'] + const useOffsetPagination: typeof import('@vueuse/core')['useOffsetPagination'] + const useOnline: typeof import('@vueuse/core')['useOnline'] + const usePageLeave: typeof import('@vueuse/core')['usePageLeave'] + const useParallax: typeof import('@vueuse/core')['useParallax'] + const useParentElement: typeof import('@vueuse/core')['useParentElement'] + const usePerformanceObserver: typeof import('@vueuse/core')['usePerformanceObserver'] + const usePermission: typeof import('@vueuse/core')['usePermission'] + const usePointer: typeof import('@vueuse/core')['usePointer'] + const usePointerLock: typeof import('@vueuse/core')['usePointerLock'] + const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe'] + const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme'] + const usePreferredContrast: typeof import('@vueuse/core')['usePreferredContrast'] + const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark'] + const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages'] + const usePreferredReducedMotion: typeof import('@vueuse/core')['usePreferredReducedMotion'] + const usePrevious: typeof import('@vueuse/core')['usePrevious'] + const useRafFn: typeof import('@vueuse/core')['useRafFn'] + const useRefHistory: typeof import('@vueuse/core')['useRefHistory'] + const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver'] + const useRoute: typeof import('vue-router')['useRoute'] + const useRouter: typeof import('vue-router')['useRouter'] + const useScreen: typeof import('@celeris/hooks')['useScreen'] + const useScreenOrientation: typeof import('@vueuse/core')['useScreenOrientation'] + const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea'] + const useScriptTag: typeof import('@vueuse/core')['useScriptTag'] + const useScroll: typeof import('@vueuse/core')['useScroll'] + const useScrollLock: typeof import('@vueuse/core')['useScrollLock'] + const useSearchDialog: typeof import('../src/composables/useSearchDialog')['useSearchDialog'] + const useSessionStorage: typeof import('@vueuse/core')['useSessionStorage'] + const useShare: typeof import('@vueuse/core')['useShare'] + const useSlots: typeof import('vue')['useSlots'] + const useSorted: typeof import('@vueuse/core')['useSorted'] + const useSpeechRecognition: typeof import('@vueuse/core')['useSpeechRecognition'] + const useSpeechSynthesis: typeof import('@vueuse/core')['useSpeechSynthesis'] + const useState: typeof import('@celeris/hooks')['useState'] + const useStepper: typeof import('@vueuse/core')['useStepper'] + const useStorage: typeof import('@vueuse/core')['useStorage'] + const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync'] + const useStyleTag: typeof import('@vueuse/core')['useStyleTag'] + const useSupported: typeof import('@vueuse/core')['useSupported'] + const useSwipe: typeof import('@vueuse/core')['useSwipe'] + const useTabs: typeof import('../src/composables/useTabs')['useTabs'] + const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList'] + const useTextDirection: typeof import('@vueuse/core')['useTextDirection'] + const useTextSelection: typeof import('@vueuse/core')['useTextSelection'] + const useTextareaAutosize: typeof import('@vueuse/core')['useTextareaAutosize'] + const useThemeSetting: typeof import('../src/composables/setting/useThemeSetting')['useThemeSetting'] + const useThrottle: typeof import('@vueuse/core')['useThrottle'] + const useThrottleFn: typeof import('@vueuse/core')['useThrottleFn'] + const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory'] + const useTimeAgo: typeof import('@vueuse/core')['useTimeAgo'] + const useTimeout: typeof import('@vueuse/core')['useTimeout'] + const useTimeoutFn: typeof import('@vueuse/core')['useTimeoutFn'] + const useTimeoutPoll: typeof import('@vueuse/core')['useTimeoutPoll'] + const useTimestamp: typeof import('@vueuse/core')['useTimestamp'] + const useTitle: typeof import('@vueuse/core')['useTitle'] + const useToNumber: typeof import('@vueuse/core')['useToNumber'] + const useToString: typeof import('@vueuse/core')['useToString'] + const useToggle: typeof import('@vueuse/core')['useToggle'] + const useTransition: typeof import('@vueuse/core')['useTransition'] + const useTransitionSetting: typeof import('../src/composables/setting/useTransitionSetting')['useTransitionSetting'] + const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams'] + const useUserMedia: typeof import('@vueuse/core')['useUserMedia'] + const useVModel: typeof import('@vueuse/core')['useVModel'] + const useVModels: typeof import('@vueuse/core')['useVModels'] + const useVibrate: typeof import('@vueuse/core')['useVibrate'] + const useVirtualList: typeof import('@vueuse/core')['useVirtualList'] + const useWakeLock: typeof import('@vueuse/core')['useWakeLock'] + const useWebNotification: typeof import('@vueuse/core')['useWebNotification'] + const useWebSocket: typeof import('@vueuse/core')['useWebSocket'] + const useWebWorker: typeof import('@vueuse/core')['useWebWorker'] + const useWebWorkerFn: typeof import('@vueuse/core')['useWebWorkerFn'] + const useWindowFocus: typeof import('@vueuse/core')['useWindowFocus'] + const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll'] + const useWindowSize: typeof import('@vueuse/core')['useWindowSize'] + const watch: typeof import('vue')['watch'] + const watchArray: typeof import('@vueuse/core')['watchArray'] + const watchAtMost: typeof import('@vueuse/core')['watchAtMost'] + const watchDebounced: typeof import('@vueuse/core')['watchDebounced'] + const watchDeep: typeof import('@vueuse/core')['watchDeep'] + const watchEffect: typeof import('vue')['watchEffect'] + const watchIgnorable: typeof import('@vueuse/core')['watchIgnorable'] + const watchImmediate: typeof import('@vueuse/core')['watchImmediate'] + const watchOnce: typeof import('@vueuse/core')['watchOnce'] + const watchPausable: typeof import('@vueuse/core')['watchPausable'] + const watchPostEffect: typeof import('vue')['watchPostEffect'] + const watchSyncEffect: typeof import('vue')['watchSyncEffect'] + const watchThrottled: typeof import('@vueuse/core')['watchThrottled'] + const watchTriggerable: typeof import('@vueuse/core')['watchTriggerable'] + const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter'] + const whenever: typeof import('@vueuse/core')['whenever'] +} +// for type re-export +declare global { + // @ts-ignore + export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue' + import('vue') +} +// for vue template auto import +import { UnwrapRef } from 'vue' +declare module 'vue' { + interface GlobalComponents {} + interface ComponentCustomProperties { + readonly EffectScope: UnwrapRef + readonly asyncComputed: UnwrapRef + readonly autoResetRef: UnwrapRef + readonly computed: UnwrapRef + readonly computedAsync: UnwrapRef + readonly computedEager: UnwrapRef + readonly computedInject: UnwrapRef + readonly computedWithControl: UnwrapRef + readonly controlledComputed: UnwrapRef + readonly controlledRef: UnwrapRef + readonly createApp: UnwrapRef + readonly createEventHook: UnwrapRef + readonly createGlobalState: UnwrapRef + readonly createInjectionState: UnwrapRef + readonly createReactiveFn: UnwrapRef + readonly createReusableTemplate: UnwrapRef + readonly createSharedComposable: UnwrapRef + readonly createTemplatePromise: UnwrapRef + readonly createUnrefFn: UnwrapRef + readonly customRef: UnwrapRef + readonly debouncedRef: UnwrapRef + readonly debouncedWatch: UnwrapRef + readonly defineAsyncComponent: UnwrapRef + readonly defineComponent: UnwrapRef + readonly eagerComputed: UnwrapRef + readonly effectScope: UnwrapRef + readonly extendRef: UnwrapRef + readonly getCurrentInstance: UnwrapRef + readonly getCurrentScope: UnwrapRef + readonly h: UnwrapRef + readonly ignorableWatch: UnwrapRef + readonly inject: UnwrapRef + readonly injectLocal: UnwrapRef + readonly isDefined: UnwrapRef + readonly isProxy: UnwrapRef + readonly isReactive: UnwrapRef + readonly isReadonly: UnwrapRef + readonly isRef: UnwrapRef + readonly makeDestructurable: UnwrapRef + readonly markRaw: UnwrapRef + readonly nextTick: UnwrapRef + readonly onActivated: UnwrapRef + readonly onBeforeMount: UnwrapRef + readonly onBeforeRouteLeave: UnwrapRef + readonly onBeforeRouteUpdate: UnwrapRef + readonly onBeforeUnmount: UnwrapRef + readonly onBeforeUpdate: UnwrapRef + readonly onClickOutside: UnwrapRef + readonly onDeactivated: UnwrapRef + readonly onErrorCaptured: UnwrapRef + readonly onKeyStroke: UnwrapRef + readonly onLongPress: UnwrapRef + readonly onMounted: UnwrapRef + readonly onRenderTracked: UnwrapRef + readonly onRenderTriggered: UnwrapRef + readonly onScopeDispose: UnwrapRef + readonly onServerPrefetch: UnwrapRef + readonly onStartTyping: UnwrapRef + readonly onUnmounted: UnwrapRef + readonly onUpdated: UnwrapRef + readonly pausableWatch: UnwrapRef + readonly provide: UnwrapRef + readonly provideLocal: UnwrapRef + readonly reactify: UnwrapRef + readonly reactifyObject: UnwrapRef + readonly reactive: UnwrapRef + readonly reactiveComputed: UnwrapRef + readonly reactiveOmit: UnwrapRef + readonly reactivePick: UnwrapRef + readonly readonly: UnwrapRef + readonly ref: UnwrapRef + readonly refAutoReset: UnwrapRef + readonly refDebounced: UnwrapRef + readonly refDefault: UnwrapRef + readonly refThrottled: UnwrapRef + readonly refWithControl: UnwrapRef + readonly resolveComponent: UnwrapRef + readonly resolveRef: UnwrapRef + readonly resolveUnref: UnwrapRef + readonly setupStore: UnwrapRef + readonly shallowReactive: UnwrapRef + readonly shallowReadonly: UnwrapRef + readonly shallowRef: UnwrapRef + readonly store: UnwrapRef + readonly syncRef: UnwrapRef + readonly syncRefs: UnwrapRef + readonly templateRef: UnwrapRef + readonly throttledRef: UnwrapRef + readonly throttledWatch: UnwrapRef + readonly toRaw: UnwrapRef + readonly toReactive: UnwrapRef + readonly toRef: UnwrapRef + readonly toRefs: UnwrapRef + readonly toValue: UnwrapRef + readonly triggerRef: UnwrapRef + readonly tryOnBeforeMount: UnwrapRef + readonly tryOnBeforeUnmount: UnwrapRef + readonly tryOnMounted: UnwrapRef + readonly tryOnScopeDispose: UnwrapRef + readonly tryOnUnmounted: UnwrapRef + readonly unref: UnwrapRef + readonly unrefElement: UnwrapRef + readonly until: UnwrapRef + readonly useActiveElement: UnwrapRef + readonly useAnimate: UnwrapRef + readonly useAppPermission: UnwrapRef + readonly useAppSetting: UnwrapRef + readonly useArrayDifference: UnwrapRef + readonly useArrayEvery: UnwrapRef + readonly useArrayFilter: UnwrapRef + readonly useArrayFind: UnwrapRef + readonly useArrayFindIndex: UnwrapRef + readonly useArrayFindLast: UnwrapRef + readonly useArrayIncludes: UnwrapRef + readonly useArrayJoin: UnwrapRef + readonly useArrayMap: UnwrapRef + readonly useArrayReduce: UnwrapRef + readonly useArraySome: UnwrapRef + readonly useArrayUnique: UnwrapRef + readonly useAsyncQueue: UnwrapRef + readonly useAsyncState: UnwrapRef + readonly useAttrs: UnwrapRef + readonly useBase64: UnwrapRef + readonly useBattery: UnwrapRef + readonly useBluetooth: UnwrapRef + readonly useBreakpoints: UnwrapRef + readonly useBroadcastChannel: UnwrapRef + readonly useBrowserLocation: UnwrapRef + readonly useCached: UnwrapRef + readonly useChartOption: UnwrapRef + readonly useClipboard: UnwrapRef + readonly useClipboardItems: UnwrapRef + readonly useCloned: UnwrapRef + readonly useColorMode: UnwrapRef + readonly useComponentRef: UnwrapRef + readonly useConfirmDialog: UnwrapRef + readonly useCounter: UnwrapRef + readonly useCssModule: UnwrapRef + readonly useCssVar: UnwrapRef + readonly useCssVars: UnwrapRef + readonly useCurrentElement: UnwrapRef + readonly useCycleList: UnwrapRef + readonly useDark: UnwrapRef + readonly useDateFormat: UnwrapRef + readonly useDebounce: UnwrapRef + readonly useDebounceFn: UnwrapRef + readonly useDebouncedRefHistory: UnwrapRef + readonly useDeviceMotion: UnwrapRef + readonly useDeviceOrientation: UnwrapRef + readonly useDevicePixelRatio: UnwrapRef + readonly useDevicesList: UnwrapRef + readonly useDialog: UnwrapRef + readonly useDisplayMedia: UnwrapRef + readonly useDocumentVisibility: UnwrapRef + readonly useDraggable: UnwrapRef + readonly useDropZone: UnwrapRef + readonly useElementBounding: UnwrapRef + readonly useElementByPoint: UnwrapRef + readonly useElementHover: UnwrapRef + readonly useElementSize: UnwrapRef + readonly useElementVisibility: UnwrapRef + readonly useEventBus: UnwrapRef + readonly useEventListener: UnwrapRef + readonly useEventSource: UnwrapRef + readonly useEyeDropper: UnwrapRef + readonly useFavicon: UnwrapRef + readonly useFetch: UnwrapRef + readonly useFileDialog: UnwrapRef + readonly useFileSystemAccess: UnwrapRef + readonly useFocus: UnwrapRef + readonly useFocusWithin: UnwrapRef + readonly useFps: UnwrapRef + readonly useFullscreen: UnwrapRef + readonly useGamepad: UnwrapRef + readonly useGeolocation: UnwrapRef + readonly useGlobSetting: UnwrapRef + readonly useHeaderSetting: UnwrapRef + readonly useI18n: UnwrapRef + readonly useIdle: UnwrapRef + readonly useImage: UnwrapRef + readonly useInfiniteScroll: UnwrapRef + readonly useIntersectionObserver: UnwrapRef + readonly useInterval: UnwrapRef + readonly useIntervalFn: UnwrapRef + readonly useKeyModifier: UnwrapRef + readonly useLastChanged: UnwrapRef + readonly useLink: UnwrapRef + readonly useLoading: UnwrapRef + readonly useLoadingBar: UnwrapRef + readonly useLocalStorage: UnwrapRef + readonly useMagicKeys: UnwrapRef + readonly useManualRefHistory: UnwrapRef + readonly useMediaControls: UnwrapRef + readonly useMediaQuery: UnwrapRef + readonly useMemoize: UnwrapRef + readonly useMemory: UnwrapRef + readonly useMenuSetting: UnwrapRef + readonly useMergeState: UnwrapRef + readonly useMessage: UnwrapRef + readonly useMounted: UnwrapRef + readonly useMouse: UnwrapRef + readonly useMouseInElement: UnwrapRef + readonly useMousePressed: UnwrapRef + readonly useMutationObserver: UnwrapRef + readonly useNaiveUIConfigProvider: UnwrapRef + readonly useNavigatorLanguage: UnwrapRef + readonly useNetwork: UnwrapRef + readonly useNotification: UnwrapRef + readonly useNow: UnwrapRef + readonly useObjectUrl: UnwrapRef + readonly useOffsetPagination: UnwrapRef + readonly useOnline: UnwrapRef + readonly usePageLeave: UnwrapRef + readonly useParallax: UnwrapRef + readonly useParentElement: UnwrapRef + readonly usePerformanceObserver: UnwrapRef + readonly usePermission: UnwrapRef + readonly usePointer: UnwrapRef + readonly usePointerLock: UnwrapRef + readonly usePointerSwipe: UnwrapRef + readonly usePreferredColorScheme: UnwrapRef + readonly usePreferredContrast: UnwrapRef + readonly usePreferredDark: UnwrapRef + readonly usePreferredLanguages: UnwrapRef + readonly usePreferredReducedMotion: UnwrapRef + readonly usePrevious: UnwrapRef + readonly useRafFn: UnwrapRef + readonly useRefHistory: UnwrapRef + readonly useResizeObserver: UnwrapRef + readonly useRoute: UnwrapRef + readonly useRouter: UnwrapRef + readonly useScreen: UnwrapRef + readonly useScreenOrientation: UnwrapRef + readonly useScreenSafeArea: UnwrapRef + readonly useScriptTag: UnwrapRef + readonly useScroll: UnwrapRef + readonly useScrollLock: UnwrapRef + readonly useSearchDialog: UnwrapRef + readonly useSessionStorage: UnwrapRef + readonly useShare: UnwrapRef + readonly useSlots: UnwrapRef + readonly useSorted: UnwrapRef + readonly useSpeechRecognition: UnwrapRef + readonly useSpeechSynthesis: UnwrapRef + readonly useState: UnwrapRef + readonly useStepper: UnwrapRef + readonly useStorage: UnwrapRef + readonly useStorageAsync: UnwrapRef + readonly useStyleTag: UnwrapRef + readonly useSupported: UnwrapRef + readonly useSwipe: UnwrapRef + readonly useTemplateRefsList: UnwrapRef + readonly useTextDirection: UnwrapRef + readonly useTextSelection: UnwrapRef + readonly useTextareaAutosize: UnwrapRef + readonly useThemeSetting: UnwrapRef + readonly useThrottle: UnwrapRef + readonly useThrottleFn: UnwrapRef + readonly useThrottledRefHistory: UnwrapRef + readonly useTimeAgo: UnwrapRef + readonly useTimeout: UnwrapRef + readonly useTimeoutFn: UnwrapRef + readonly useTimeoutPoll: UnwrapRef + readonly useTimestamp: UnwrapRef + readonly useTitle: UnwrapRef + readonly useToNumber: UnwrapRef + readonly useToString: UnwrapRef + readonly useToggle: UnwrapRef + readonly useTransition: UnwrapRef + readonly useTransitionSetting: UnwrapRef + readonly useUrlSearchParams: UnwrapRef + readonly useUserMedia: UnwrapRef + readonly useVModel: UnwrapRef + readonly useVModels: UnwrapRef + readonly useVibrate: UnwrapRef + readonly useVirtualList: UnwrapRef + readonly useWakeLock: UnwrapRef + readonly useWebNotification: UnwrapRef + readonly useWebSocket: UnwrapRef + readonly useWebWorker: UnwrapRef + readonly useWebWorkerFn: UnwrapRef + readonly useWindowFocus: UnwrapRef + readonly useWindowScroll: UnwrapRef + readonly useWindowSize: UnwrapRef + readonly watch: UnwrapRef + readonly watchArray: UnwrapRef + readonly watchAtMost: UnwrapRef + readonly watchDebounced: UnwrapRef + readonly watchDeep: UnwrapRef + readonly watchEffect: UnwrapRef + readonly watchIgnorable: UnwrapRef + readonly watchImmediate: UnwrapRef + readonly watchOnce: UnwrapRef + readonly watchPausable: UnwrapRef + readonly watchPostEffect: UnwrapRef + readonly watchSyncEffect: UnwrapRef + readonly watchThrottled: UnwrapRef + readonly watchTriggerable: UnwrapRef + readonly watchWithFilter: UnwrapRef + readonly whenever: UnwrapRef + } +} +declare module '@vue/runtime-core' { + interface GlobalComponents {} + interface ComponentCustomProperties { + readonly EffectScope: UnwrapRef + readonly asyncComputed: UnwrapRef + readonly autoResetRef: UnwrapRef + readonly computed: UnwrapRef + readonly computedAsync: UnwrapRef + readonly computedEager: UnwrapRef + readonly computedInject: UnwrapRef + readonly computedWithControl: UnwrapRef + readonly controlledComputed: UnwrapRef + readonly controlledRef: UnwrapRef + readonly createApp: UnwrapRef + readonly createEventHook: UnwrapRef + readonly createGlobalState: UnwrapRef + readonly createInjectionState: UnwrapRef + readonly createReactiveFn: UnwrapRef + readonly createReusableTemplate: UnwrapRef + readonly createSharedComposable: UnwrapRef + readonly createTemplatePromise: UnwrapRef + readonly createUnrefFn: UnwrapRef + readonly customRef: UnwrapRef + readonly debouncedRef: UnwrapRef + readonly debouncedWatch: UnwrapRef + readonly defineAsyncComponent: UnwrapRef + readonly defineComponent: UnwrapRef + readonly eagerComputed: UnwrapRef + readonly effectScope: UnwrapRef + readonly extendRef: UnwrapRef + readonly getCurrentInstance: UnwrapRef + readonly getCurrentScope: UnwrapRef + readonly h: UnwrapRef + readonly ignorableWatch: UnwrapRef + readonly inject: UnwrapRef + readonly injectLocal: UnwrapRef + readonly isDefined: UnwrapRef + readonly isProxy: UnwrapRef + readonly isReactive: UnwrapRef + readonly isReadonly: UnwrapRef + readonly isRef: UnwrapRef + readonly makeDestructurable: UnwrapRef + readonly markRaw: UnwrapRef + readonly nextTick: UnwrapRef + readonly onActivated: UnwrapRef + readonly onBeforeMount: UnwrapRef + readonly onBeforeRouteLeave: UnwrapRef + readonly onBeforeRouteUpdate: UnwrapRef + readonly onBeforeUnmount: UnwrapRef + readonly onBeforeUpdate: UnwrapRef + readonly onClickOutside: UnwrapRef + readonly onDeactivated: UnwrapRef + readonly onErrorCaptured: UnwrapRef + readonly onKeyStroke: UnwrapRef + readonly onLongPress: UnwrapRef + readonly onMounted: UnwrapRef + readonly onRenderTracked: UnwrapRef + readonly onRenderTriggered: UnwrapRef + readonly onScopeDispose: UnwrapRef + readonly onServerPrefetch: UnwrapRef + readonly onStartTyping: UnwrapRef + readonly onUnmounted: UnwrapRef + readonly onUpdated: UnwrapRef + readonly pausableWatch: UnwrapRef + readonly provide: UnwrapRef + readonly provideLocal: UnwrapRef + readonly reactify: UnwrapRef + readonly reactifyObject: UnwrapRef + readonly reactive: UnwrapRef + readonly reactiveComputed: UnwrapRef + readonly reactiveOmit: UnwrapRef + readonly reactivePick: UnwrapRef + readonly readonly: UnwrapRef + readonly ref: UnwrapRef + readonly refAutoReset: UnwrapRef + readonly refDebounced: UnwrapRef + readonly refDefault: UnwrapRef + readonly refThrottled: UnwrapRef + readonly refWithControl: UnwrapRef + readonly resolveComponent: UnwrapRef + readonly resolveRef: UnwrapRef + readonly resolveUnref: UnwrapRef + readonly setupStore: UnwrapRef + readonly shallowReactive: UnwrapRef + readonly shallowReadonly: UnwrapRef + readonly shallowRef: UnwrapRef + readonly store: UnwrapRef + readonly syncRef: UnwrapRef + readonly syncRefs: UnwrapRef + readonly templateRef: UnwrapRef + readonly throttledRef: UnwrapRef + readonly throttledWatch: UnwrapRef + readonly toRaw: UnwrapRef + readonly toReactive: UnwrapRef + readonly toRef: UnwrapRef + readonly toRefs: UnwrapRef + readonly toValue: UnwrapRef + readonly triggerRef: UnwrapRef + readonly tryOnBeforeMount: UnwrapRef + readonly tryOnBeforeUnmount: UnwrapRef + readonly tryOnMounted: UnwrapRef + readonly tryOnScopeDispose: UnwrapRef + readonly tryOnUnmounted: UnwrapRef + readonly unref: UnwrapRef + readonly unrefElement: UnwrapRef + readonly until: UnwrapRef + readonly useActiveElement: UnwrapRef + readonly useAnimate: UnwrapRef + readonly useAppPermission: UnwrapRef + readonly useAppSetting: UnwrapRef + readonly useArrayDifference: UnwrapRef + readonly useArrayEvery: UnwrapRef + readonly useArrayFilter: UnwrapRef + readonly useArrayFind: UnwrapRef + readonly useArrayFindIndex: UnwrapRef + readonly useArrayFindLast: UnwrapRef + readonly useArrayIncludes: UnwrapRef + readonly useArrayJoin: UnwrapRef + readonly useArrayMap: UnwrapRef + readonly useArrayReduce: UnwrapRef + readonly useArraySome: UnwrapRef + readonly useArrayUnique: UnwrapRef + readonly useAsyncQueue: UnwrapRef + readonly useAsyncState: UnwrapRef + readonly useAttrs: UnwrapRef + readonly useBase64: UnwrapRef + readonly useBattery: UnwrapRef + readonly useBluetooth: UnwrapRef + readonly useBreakpoints: UnwrapRef + readonly useBroadcastChannel: UnwrapRef + readonly useBrowserLocation: UnwrapRef + readonly useCached: UnwrapRef + readonly useChartOption: UnwrapRef + readonly useClipboard: UnwrapRef + readonly useClipboardItems: UnwrapRef + readonly useCloned: UnwrapRef + readonly useColorMode: UnwrapRef + readonly useComponentRef: UnwrapRef + readonly useConfirmDialog: UnwrapRef + readonly useCounter: UnwrapRef + readonly useCssModule: UnwrapRef + readonly useCssVar: UnwrapRef + readonly useCssVars: UnwrapRef + readonly useCurrentElement: UnwrapRef + readonly useCycleList: UnwrapRef + readonly useDark: UnwrapRef + readonly useDateFormat: UnwrapRef + readonly useDebounce: UnwrapRef + readonly useDebounceFn: UnwrapRef + readonly useDebouncedRefHistory: UnwrapRef + readonly useDeviceMotion: UnwrapRef + readonly useDeviceOrientation: UnwrapRef + readonly useDevicePixelRatio: UnwrapRef + readonly useDevicesList: UnwrapRef + readonly useDialog: UnwrapRef + readonly useDisplayMedia: UnwrapRef + readonly useDocumentVisibility: UnwrapRef + readonly useDraggable: UnwrapRef + readonly useDropZone: UnwrapRef + readonly useElementBounding: UnwrapRef + readonly useElementByPoint: UnwrapRef + readonly useElementHover: UnwrapRef + readonly useElementSize: UnwrapRef + readonly useElementVisibility: UnwrapRef + readonly useEventBus: UnwrapRef + readonly useEventListener: UnwrapRef + readonly useEventSource: UnwrapRef + readonly useEyeDropper: UnwrapRef + readonly useFavicon: UnwrapRef + readonly useFetch: UnwrapRef + readonly useFileDialog: UnwrapRef + readonly useFileSystemAccess: UnwrapRef + readonly useFocus: UnwrapRef + readonly useFocusWithin: UnwrapRef + readonly useFps: UnwrapRef + readonly useFullscreen: UnwrapRef + readonly useGamepad: UnwrapRef + readonly useGeolocation: UnwrapRef + readonly useGlobSetting: UnwrapRef + readonly useHeaderSetting: UnwrapRef + readonly useI18n: UnwrapRef + readonly useIdle: UnwrapRef + readonly useImage: UnwrapRef + readonly useInfiniteScroll: UnwrapRef + readonly useIntersectionObserver: UnwrapRef + readonly useInterval: UnwrapRef + readonly useIntervalFn: UnwrapRef + readonly useKeyModifier: UnwrapRef + readonly useLastChanged: UnwrapRef + readonly useLink: UnwrapRef + readonly useLoading: UnwrapRef + readonly useLoadingBar: UnwrapRef + readonly useLocalStorage: UnwrapRef + readonly useMagicKeys: UnwrapRef + readonly useManualRefHistory: UnwrapRef + readonly useMediaControls: UnwrapRef + readonly useMediaQuery: UnwrapRef + readonly useMemoize: UnwrapRef + readonly useMemory: UnwrapRef + readonly useMenuSetting: UnwrapRef + readonly useMergeState: UnwrapRef + readonly useMessage: UnwrapRef + readonly useMounted: UnwrapRef + readonly useMouse: UnwrapRef + readonly useMouseInElement: UnwrapRef + readonly useMousePressed: UnwrapRef + readonly useMutationObserver: UnwrapRef + readonly useNaiveUIConfigProvider: UnwrapRef + readonly useNavigatorLanguage: UnwrapRef + readonly useNetwork: UnwrapRef + readonly useNotification: UnwrapRef + readonly useNow: UnwrapRef + readonly useObjectUrl: UnwrapRef + readonly useOffsetPagination: UnwrapRef + readonly useOnline: UnwrapRef + readonly usePageLeave: UnwrapRef + readonly useParallax: UnwrapRef + readonly useParentElement: UnwrapRef + readonly usePerformanceObserver: UnwrapRef + readonly usePermission: UnwrapRef + readonly usePointer: UnwrapRef + readonly usePointerLock: UnwrapRef + readonly usePointerSwipe: UnwrapRef + readonly usePreferredColorScheme: UnwrapRef + readonly usePreferredContrast: UnwrapRef + readonly usePreferredDark: UnwrapRef + readonly usePreferredLanguages: UnwrapRef + readonly usePreferredReducedMotion: UnwrapRef + readonly usePrevious: UnwrapRef + readonly useRafFn: UnwrapRef + readonly useRefHistory: UnwrapRef + readonly useResizeObserver: UnwrapRef + readonly useRoute: UnwrapRef + readonly useRouter: UnwrapRef + readonly useScreen: UnwrapRef + readonly useScreenOrientation: UnwrapRef + readonly useScreenSafeArea: UnwrapRef + readonly useScriptTag: UnwrapRef + readonly useScroll: UnwrapRef + readonly useScrollLock: UnwrapRef + readonly useSearchDialog: UnwrapRef + readonly useSessionStorage: UnwrapRef + readonly useShare: UnwrapRef + readonly useSlots: UnwrapRef + readonly useSorted: UnwrapRef + readonly useSpeechRecognition: UnwrapRef + readonly useSpeechSynthesis: UnwrapRef + readonly useState: UnwrapRef + readonly useStepper: UnwrapRef + readonly useStorage: UnwrapRef + readonly useStorageAsync: UnwrapRef + readonly useStyleTag: UnwrapRef + readonly useSupported: UnwrapRef + readonly useSwipe: UnwrapRef + readonly useTemplateRefsList: UnwrapRef + readonly useTextDirection: UnwrapRef + readonly useTextSelection: UnwrapRef + readonly useTextareaAutosize: UnwrapRef + readonly useThemeSetting: UnwrapRef + readonly useThrottle: UnwrapRef + readonly useThrottleFn: UnwrapRef + readonly useThrottledRefHistory: UnwrapRef + readonly useTimeAgo: UnwrapRef + readonly useTimeout: UnwrapRef + readonly useTimeoutFn: UnwrapRef + readonly useTimeoutPoll: UnwrapRef + readonly useTimestamp: UnwrapRef + readonly useTitle: UnwrapRef + readonly useToNumber: UnwrapRef + readonly useToString: UnwrapRef + readonly useToggle: UnwrapRef + readonly useTransition: UnwrapRef + readonly useTransitionSetting: UnwrapRef + readonly useUrlSearchParams: UnwrapRef + readonly useUserMedia: UnwrapRef + readonly useVModel: UnwrapRef + readonly useVModels: UnwrapRef + readonly useVibrate: UnwrapRef + readonly useVirtualList: UnwrapRef + readonly useWakeLock: UnwrapRef + readonly useWebNotification: UnwrapRef + readonly useWebSocket: UnwrapRef + readonly useWebWorker: UnwrapRef + readonly useWebWorkerFn: UnwrapRef + readonly useWindowFocus: UnwrapRef + readonly useWindowScroll: UnwrapRef + readonly useWindowSize: UnwrapRef + readonly watch: UnwrapRef + readonly watchArray: UnwrapRef + readonly watchAtMost: UnwrapRef + readonly watchDebounced: UnwrapRef + readonly watchDeep: UnwrapRef + readonly watchEffect: UnwrapRef + readonly watchIgnorable: UnwrapRef + readonly watchImmediate: UnwrapRef + readonly watchOnce: UnwrapRef + readonly watchPausable: UnwrapRef + readonly watchPostEffect: UnwrapRef + readonly watchSyncEffect: UnwrapRef + readonly watchThrottled: UnwrapRef + readonly watchTriggerable: UnwrapRef + readonly watchWithFilter: UnwrapRef + readonly whenever: UnwrapRef + } +} diff --git a/apps/thin/autoResolver/components.d.ts b/apps/thin/autoResolver/components.d.ts new file mode 100644 index 00000000..df0a12a2 --- /dev/null +++ b/apps/thin/autoResolver/components.d.ts @@ -0,0 +1,71 @@ +/* eslint-disable */ +// @ts-nocheck +// Generated by unplugin-vue-components +// Read more: https://github.com/vuejs/core/pull/3399 +export {} + +/* prettier-ignore */ +declare module 'vue' { + export interface GlobalComponents { + CAAppLogo: typeof import('@celeris/components')['CAAppLogo'] + CAAppNaiveUIProvider: typeof import('@celeris/components')['CAAppNaiveUIProvider'] + CACharts: typeof import('@celeris/components')['CACharts'] + CAIcon: typeof import('@celeris/components')['CAIcon'] + NAlert: typeof import('@celeris/ca-components')['NAlert'] + NAvatar: typeof import('@celeris/ca-components')['NAvatar'] + NBadge: typeof import('@celeris/ca-components')['NBadge'] + NBreadcrumb: typeof import('@celeris/ca-components')['NBreadcrumb'] + NBreadcrumbItem: typeof import('@celeris/ca-components')['NBreadcrumbItem'] + NButton: typeof import('@celeris/ca-components')['NButton'] + NCard: typeof import('@celeris/ca-components')['NCard'] + NCheckbox: typeof import('@celeris/ca-components')['NCheckbox'] + NCol: typeof import('@celeris/ca-components')['NCol'] + NCollapse: typeof import('@celeris/ca-components')['NCollapse'] + NCollapseItem: typeof import('@celeris/ca-components')['NCollapseItem'] + NColorPicker: typeof import('@celeris/ca-components')['NColorPicker'] + NConfigProvider: typeof import('@celeris/ca-components')['NConfigProvider'] + NDescriptions: typeof import('@celeris/ca-components')['NDescriptions'] + NDescriptionsItem: typeof import('@celeris/ca-components')['NDescriptionsItem'] + NDialogProvider: typeof import('@celeris/ca-components')['NDialogProvider'] + NDivider: typeof import('@celeris/ca-components')['NDivider'] + NDrawer: typeof import('@celeris/ca-components')['NDrawer'] + NDrawerContent: typeof import('@celeris/ca-components')['NDrawerContent'] + NDropdown: typeof import('@celeris/ca-components')['NDropdown'] + NEl: typeof import('@celeris/ca-components')['NEl'] + NEmpty: typeof import('@celeris/ca-components')['NEmpty'] + NForm: typeof import('@celeris/ca-components')['NForm'] + NFormItem: typeof import('@celeris/ca-components')['NFormItem'] + NGlobalStyle: typeof import('@celeris/ca-components')['NGlobalStyle'] + NGrid: typeof import('@celeris/ca-components')['NGrid'] + NGridItem: typeof import('@celeris/ca-components')['NGridItem'] + NInput: typeof import('@celeris/ca-components')['NInput'] + NLayout: typeof import('@celeris/ca-components')['NLayout'] + NLayoutContent: typeof import('@celeris/ca-components')['NLayoutContent'] + NLayoutSider: typeof import('@celeris/ca-components')['NLayoutSider'] + NLoadingBarProvider: typeof import('@celeris/ca-components')['NLoadingBarProvider'] + NMenu: typeof import('@celeris/ca-components')['NMenu'] + NMessageProvider: typeof import('@celeris/ca-components')['NMessageProvider'] + NModal: typeof import('@celeris/ca-components')['NModal'] + NNotificationProvider: typeof import('@celeris/ca-components')['NNotificationProvider'] + NPagination: typeof import('@celeris/ca-components')['NPagination'] + NPopover: typeof import('@celeris/ca-components')['NPopover'] + NResult: typeof import('@celeris/ca-components')['NResult'] + NRow: typeof import('@celeris/ca-components')['NRow'] + NScrollbar: typeof import('@celeris/ca-components')['NScrollbar'] + NSelect: typeof import('@celeris/ca-components')['NSelect'] + NSpace: typeof import('@celeris/ca-components')['NSpace'] + NSpin: typeof import('@celeris/ca-components')['NSpin'] + NSplit: typeof import('@celeris/ca-components')['NSplit'] + NStatistic: typeof import('@celeris/ca-components')['NStatistic'] + NStep: typeof import('@celeris/ca-components')['NStep'] + NSteps: typeof import('@celeris/ca-components')['NSteps'] + NSwitch: typeof import('@celeris/ca-components')['NSwitch'] + NTable: typeof import('@celeris/ca-components')['NTable'] + NText: typeof import('@celeris/ca-components')['NText'] + NTime: typeof import('@celeris/ca-components')['NTime'] + NTooltip: typeof import('@celeris/ca-components')['NTooltip'] + NVirtualList: typeof import('@celeris/ca-components')['NVirtualList'] + RouterLink: typeof import('vue-router')['RouterLink'] + RouterView: typeof import('vue-router')['RouterView'] + } +} diff --git a/apps/thin/index.html b/apps/thin/index.html new file mode 100644 index 00000000..e0083181 --- /dev/null +++ b/apps/thin/index.html @@ -0,0 +1,115 @@ + + + + + + + Celeris Web + + + + +
+ +
+
+
+
+
+
+ + + + diff --git a/apps/thin/package.json b/apps/thin/package.json new file mode 100644 index 00000000..c586313d --- /dev/null +++ b/apps/thin/package.json @@ -0,0 +1,64 @@ +{ + "name": "@celeris/admin-thin", + "type": "module", + "version": "0.0.2", + "packageManager": "pnpm@9.1.0", + "description": "Celeris Web", + "author": "Kirk Lin (https://github.com/kirklin)", + "license": "MIT", + "homepage": "https://github.com/kirklin/celeris-web", + "keywords": [ + "celeris-web-admin", + "celeris-web", + "celeris", + "vite", + "unocss", + "fast", + "boot" + ], + "main": "src/main.ts", + "scripts": { + "dev": "vite", + "build": "pnpm cross-env NODE_ENV=production vite build", + "clean": "pnpm rimraf node_modules && pnpm rimraf dist", + "typecheck": "vue-tsc --noEmit --skipLibCheck", + "preview": "npm run build && vite preview", + "preview:dist": "vite preview" + }, + "dependencies": { + "@celeris/constants": "workspace:*", + "@celeris/directives": "workspace:*", + "@celeris/locale": "workspace:*", + "@celeris/request": "workspace:*", + "@celeris/styles": "workspace:*", + "@celeris/utils": "workspace:*", + "destr": "^2.0.3", + "headless-highlighter": "^0.0.0", + "nprogress": "^0.2.0", + "pinia": "^2.1.7", + "pinia-plugin-persistedstate": "^3.2.1", + "pkg-types": "^1.1.0", + "vue": "^3.4.27", + "vue-i18n": "^9.13.1", + "vue-router": "^4.3.2" + }, + "devDependencies": { + "@celeris/admin-api": "workspace:*", + "@celeris/assets": "workspace:*", + "@celeris/ca-components": "workspace:*", + "@celeris/components": "workspace:*", + "@celeris/hooks": "workspace:*", + "@celeris/types": "workspace:*", + "@celeris/vite": "workspace:*", + "@vitejs/plugin-vue": "^5.0.4", + "@vue/compiler-dom": "^3.4.27", + "@vue/test-utils": "^2.4.6", + "jsdom": "^24.0.0", + "pnpm": "^9.1.0", + "typescript": "^5.4.5", + "unocss": "^0.60.0", + "vite": "^5.2.11", + "vitest": "^1.6.0", + "vue-tsc": "^2.0.16" + } +} diff --git a/apps/thin/public/favicon.ico b/apps/thin/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..94ef03ec981fe4c278e64f70ab55842bfce0257a GIT binary patch literal 67646 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 literal 0 HcmV?d00001 diff --git a/apps/thin/src/App.vue b/apps/thin/src/App.vue new file mode 100644 index 00000000..180ea233 --- /dev/null +++ b/apps/thin/src/App.vue @@ -0,0 +1,21 @@ + + + diff --git a/apps/thin/src/AppConfiguration.ts b/apps/thin/src/AppConfiguration.ts new file mode 100644 index 00000000..2ce1f181 --- /dev/null +++ b/apps/thin/src/AppConfiguration.ts @@ -0,0 +1,96 @@ +import { HttpRequestEngine } from "@celeris/request"; +import { LocalesEngine } from "@celeris/locale"; +import { createDiscreteApi } from "@celeris/ca-components"; +import { field, logger } from "@celeris/utils"; +import { useUserStoreWithOut } from "~/store/modules/user"; +import { useAppSetting, useNaiveUIConfigProvider } from "~/composables"; + +function initializeHttpRequest() { + const { configProviderProps } = useNaiveUIConfigProvider(); + + const { message: _message, notification, dialog } = createDiscreteApi( + ["message", "dialog", "notification", "loadingBar"], + { + configProviderProps, + }, + ); + HttpRequestEngine.initRequest(() => ({ + getToken: () => { + const userStore = useUserStoreWithOut(); + return userStore.getToken; + }, + })); + HttpRequestEngine.setTimeoutHandler(() => { + const userStore = useUserStoreWithOut(); + userStore.setToken(undefined); + userStore.logout(true).then(() => {}); + }); + HttpRequestEngine.setUnauthorizedHandler(() => { + const userStore = useUserStoreWithOut(); + userStore.setToken(undefined); + userStore.logout(true).then(() => {}); + }); + HttpRequestEngine.setMessageHandler((message, mode) => { + if (mode === "message") { + _message.info(message); + } else if (mode === "dialog") { + dialog.info({ title: "Information", content: message }); + } else if (mode === "notification") { + notification.info({ title: "Information", content: message }); + } else if (mode === undefined || mode === "none") { + logger.info(`HttpRequestEngine MessageHandler: ${message}`); + } + }); + HttpRequestEngine.setSuccessMessageHandler((message, mode) => { + if (mode === "message") { + _message.success(message); + } else if (mode === "dialog") { + dialog.success({ title: "Success", content: message }); + } else if (mode === "notification") { + notification.success({ title: "Success", content: message }); + } else if (mode === undefined || mode === "none") { + logger.info(`HttpRequestEngine SuccessHandler: ${message}`); + } + }); + HttpRequestEngine.setErrorMessageHandler((message, mode) => { + if (mode === "message") { + _message.error(message); + } else if (mode === "dialog") { + dialog.error({ title: "Error", content: message }); + } else if (mode === "notification") { + notification.error({ title: "Error", content: message }); + } else if (mode === undefined || mode === "none") { + logger.error("HttpRequestEngine ErrorHandler", field("content:", message)); + } + }); +} + +function initializeI18n() { + const { getLocale } = useAppSetting(); + const messages = Object.fromEntries( + Object.entries( + import.meta.glob<{ default: any }>("./locales/*.json", { eager: true }), + ).map(([key, value]) => { + return [key.slice(10, -5), value.default]; + }), + ); + LocalesEngine.initLocales(() => ({ + locale: getLocale.value, + fallbackLocale: "en", + messagesHandler: () => { + return messages; + }, + otherOptions: { + sync: true, + availableLocales: Object.keys(messages), + silentTranslationWarn: true, + missingWarn: false, + silentFallbackWarn: true, + }, + })); +} + +export function initializeConfiguration() { + initializeHttpRequest(); + initializeI18n(); +} diff --git a/apps/thin/src/apis/index.ts b/apps/thin/src/apis/index.ts new file mode 100644 index 00000000..d5cc7845 --- /dev/null +++ b/apps/thin/src/apis/index.ts @@ -0,0 +1,25 @@ +import type { App } from "vue"; +import type { VueQueryPluginOptions } from "@tanstack/vue-query"; +import { VueQueryPlugin } from "@tanstack/vue-query"; +import { persistQueryClient } from "@tanstack/query-persist-client-core"; +import { createSyncStoragePersister } from "@tanstack/query-sync-storage-persister"; + +const vueQueryOptions: VueQueryPluginOptions = { + queryClientConfig: { + defaultOptions: { + queries: { + staleTime: 1000 * 60 * 60 * 24, + }, + }, + }, + clientPersister: (queryClient) => { + return persistQueryClient({ + queryClient, + persister: createSyncStoragePersister({ storage: localStorage }), + }); + }, +}; + +export function setupVueQuery(app: App) { + app.use(VueQueryPlugin, vueQueryOptions); +} diff --git a/apps/thin/src/apis/internal/auth.ts b/apps/thin/src/apis/internal/auth.ts new file mode 100644 index 00000000..145171b6 --- /dev/null +++ b/apps/thin/src/apis/internal/auth.ts @@ -0,0 +1,85 @@ +import type { FakeUserInfo } from "@celeris/admin-api/models/auth/FakeUserInfo"; +import type { MessageMode, UserInfo } from "@celeris/types"; +import { request } from "@celeris/request"; + +// Define the API endpoint URLs as an enum +enum API { + Login = "/auth/login", + Logout = "/auth/logout", + UserInfo = "/user/info", + PermissionCode = "/auth/permission-code", +} + +// Define the parameters for the login API +export interface LoginParams { + username: string; + password: string; +} + +// Define a function to call the login API +export function loginApi( + params: LoginParams, + errorMessageMode: MessageMode = "dialog", +) { + // Make a POST request to the login API endpoint with the given parameters + return request.post>( + { + url: API.Login, + params, + }, + // Set the error message mode for the request + { + errorMessageMode, + }, + ); +} + +// Define a function to call the logout API +export function logoutApi( + errorMessageMode: MessageMode = "dialog", +) { + // Make a GET request to the logout API endpoint + return request.get( + { + url: API.Logout, + }, + // Set the error message mode for the request + { + errorMessageMode, + }, + ); +} + +// Define a function to call the user info API +export function userInfoApi( + errorMessageMode: MessageMode = "none", +) { + // Make a GET request to the user info API endpoint + return request.get( + { + url: API.UserInfo, + }, + // Set the error message mode for the request + { + errorMessageMode, + }, + ); +} + +// Define a function to call the permission code API +export function permissionCodeApi( + errorMessageMode: MessageMode = "dialog", +) { + // Make a GET request to the permission code API endpoint + return request.get( + { + url: API.PermissionCode, + }, + // Set the error message mode for the request + { + errorMessageMode, + }, + ); +} + +export { API }; diff --git a/apps/thin/src/apis/internal/dashboard.ts b/apps/thin/src/apis/internal/dashboard.ts new file mode 100644 index 00000000..9961497a --- /dev/null +++ b/apps/thin/src/apis/internal/dashboard.ts @@ -0,0 +1,26 @@ +import { request } from "@celeris/request"; + +// Define the API endpoint URLs as an enum +enum API { + queryDataOverview = "/dashboard/data-overview", + queryUserAnalysisData = "/dashboard/user-analysis-data", +} + +export interface DataOverviewRes { + xAxis: string[]; + data: Array<{ name: string; value: number[]; count: number }>; +} +export interface UserAnalysisDataRes { + count: number; + growth: number; + chartData: { + xAxis: string[]; + data: { name: string; value: number[] }; + }; +} +export function queryDataOverview() { + return request.post({ url: API.queryDataOverview }); +} +export function queryUserAnalysisData(params: { quota: string }) { + return request.post({ url: API.queryUserAnalysisData, params }); +} diff --git a/apps/thin/src/apis/internal/menu.ts b/apps/thin/src/apis/internal/menu.ts new file mode 100644 index 00000000..43ce2dad --- /dev/null +++ b/apps/thin/src/apis/internal/menu.ts @@ -0,0 +1,26 @@ +import type { RouteItem } from "@celeris/admin-api/models/menu/RouteItem"; +import type { MessageMode } from "@celeris/types"; +import { request } from "@celeris/request"; + +// Define the API endpoint URLs as an enum +enum API { + Menus = "/menu/list", +} + +// Define a function to call the menus API +export function menusApi( + errorMessageMode: MessageMode = "message", +) { + // Make a GET request to the logout API endpoint + return request.get( + { + url: API.Menus, + }, + // Set the error message mode for the request + { + errorMessageMode, + }, + ); +} + +export { API }; diff --git a/apps/thin/src/component/ActionIcon/index.ts b/apps/thin/src/component/ActionIcon/index.ts new file mode 100644 index 00000000..e2da4cbf --- /dev/null +++ b/apps/thin/src/component/ActionIcon/index.ts @@ -0,0 +1,6 @@ +import { withInstall } from "@celeris/utils"; +import actionIcon from "./src/ActionIcon.vue"; +import toolTipper from "./src/ToolTipper.vue"; + +export const ActionIcon = withInstall(actionIcon); +export const ToolTipper = withInstall(toolTipper); diff --git a/apps/thin/src/component/ActionIcon/src/ActionIcon.vue b/apps/thin/src/component/ActionIcon/src/ActionIcon.vue new file mode 100644 index 00000000..9b0a75e6 --- /dev/null +++ b/apps/thin/src/component/ActionIcon/src/ActionIcon.vue @@ -0,0 +1,35 @@ + + + + + diff --git a/apps/thin/src/component/ActionIcon/src/ToolTipper.vue b/apps/thin/src/component/ActionIcon/src/ToolTipper.vue new file mode 100644 index 00000000..f026b6e3 --- /dev/null +++ b/apps/thin/src/component/ActionIcon/src/ToolTipper.vue @@ -0,0 +1,45 @@ + + + + + diff --git a/apps/thin/src/component/Authority/index.ts b/apps/thin/src/component/Authority/index.ts new file mode 100644 index 00000000..b42a2f70 --- /dev/null +++ b/apps/thin/src/component/Authority/index.ts @@ -0,0 +1,4 @@ +import { withInstall } from "@celeris/utils"; +import authority from "./src/Authority.vue"; + +export const Authority = withInstall(authority); diff --git a/apps/thin/src/component/Authority/src/Authority.vue b/apps/thin/src/component/Authority/src/Authority.vue new file mode 100644 index 00000000..95a0c8fb --- /dev/null +++ b/apps/thin/src/component/Authority/src/Authority.vue @@ -0,0 +1,25 @@ + + + diff --git a/apps/thin/src/component/Card/index.ts b/apps/thin/src/component/Card/index.ts new file mode 100644 index 00000000..fb954cc7 --- /dev/null +++ b/apps/thin/src/component/Card/index.ts @@ -0,0 +1,6 @@ +import { withInstall } from "@celeris/utils"; +import dataInsightCard from "./src/DataInsightCard.vue"; +import dataCard from "./src/DataCard.vue"; + +export const DataInsightCard = withInstall(dataInsightCard); +export const DataCard = withInstall(dataCard); diff --git a/apps/thin/src/component/Card/src/DataCard.vue b/apps/thin/src/component/Card/src/DataCard.vue new file mode 100644 index 00000000..30b47f0e --- /dev/null +++ b/apps/thin/src/component/Card/src/DataCard.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/apps/thin/src/component/Card/src/DataInsightCard.vue b/apps/thin/src/component/Card/src/DataInsightCard.vue new file mode 100644 index 00000000..58e3230d --- /dev/null +++ b/apps/thin/src/component/Card/src/DataInsightCard.vue @@ -0,0 +1,64 @@ + + + + + diff --git a/apps/thin/src/component/PageWrapper/index.ts b/apps/thin/src/component/PageWrapper/index.ts new file mode 100644 index 00000000..1027a0ce --- /dev/null +++ b/apps/thin/src/component/PageWrapper/index.ts @@ -0,0 +1,4 @@ +import { withInstall } from "@celeris/utils"; +import pageWrapper from "./src/PageWrapper.vue"; + +export const PageWrapper = withInstall(pageWrapper); diff --git a/apps/thin/src/component/PageWrapper/src/PageWrapper.vue b/apps/thin/src/component/PageWrapper/src/PageWrapper.vue new file mode 100644 index 00000000..27a90406 --- /dev/null +++ b/apps/thin/src/component/PageWrapper/src/PageWrapper.vue @@ -0,0 +1,30 @@ + + + + + diff --git a/apps/thin/src/component/SearchDialog/index.ts b/apps/thin/src/component/SearchDialog/index.ts new file mode 100644 index 00000000..765e9431 --- /dev/null +++ b/apps/thin/src/component/SearchDialog/index.ts @@ -0,0 +1,4 @@ +import { withInstall } from "@celeris/utils"; +import searchDialog from "./src/SearchDialog.vue"; + +export const SearchDialog = withInstall(searchDialog); diff --git a/apps/thin/src/component/SearchDialog/src/SearchDialog.vue b/apps/thin/src/component/SearchDialog/src/SearchDialog.vue new file mode 100644 index 00000000..73084279 --- /dev/null +++ b/apps/thin/src/component/SearchDialog/src/SearchDialog.vue @@ -0,0 +1,348 @@ + + + + + diff --git a/apps/thin/src/component/SearchDialog/src/types.ts b/apps/thin/src/component/SearchDialog/src/types.ts new file mode 100644 index 00000000..09d47a9b --- /dev/null +++ b/apps/thin/src/component/SearchDialog/src/types.ts @@ -0,0 +1,15 @@ +export interface SearchGroupItem { + iconName: string | null | undefined; + iconImage: string | null; + key: number | string; + title: string; + label: string; + tags?: string; + action: () => void; +} + +export interface SearchGroup { + name: string; + items: SearchGroupItem[]; +} +export type SearchGroups = SearchGroup[]; diff --git a/apps/thin/src/composables/index.ts b/apps/thin/src/composables/index.ts new file mode 100644 index 00000000..17b8f8eb --- /dev/null +++ b/apps/thin/src/composables/index.ts @@ -0,0 +1,3 @@ +export * from "./setting"; +export * from "./useChartOption"; +export * from "./useNaiveUIConfigProvider"; diff --git a/apps/thin/src/composables/setting/index.ts b/apps/thin/src/composables/setting/index.ts new file mode 100644 index 00000000..616acb6e --- /dev/null +++ b/apps/thin/src/composables/setting/index.ts @@ -0,0 +1,7 @@ +export * from "./useAppSetting"; +export * from "./useGlobSetting"; +export * from "./useHeaderSetting"; +export * from "./useMenuSetting"; +export * from "./usePermissionSetting"; +export * from "./useThemeSetting"; +export * from "./useTransitionSetting"; diff --git a/apps/thin/src/composables/setting/useAppSetting.ts b/apps/thin/src/composables/setting/useAppSetting.ts new file mode 100644 index 00000000..d12f2a76 --- /dev/null +++ b/apps/thin/src/composables/setting/useAppSetting.ts @@ -0,0 +1,113 @@ +import type { ProjectSetting } from "@celeris/types"; +import { useAppStoreWithOut } from "~/store/modules/app"; + +export function useAppSetting() { + const appStore = useAppStoreWithOut(); + + // 获取是否显示配置按钮 + // Get whether to display the setting button + const getShouldShowSettingButton = toRef(() => appStore.getProjectSetting.shouldShowSettingButton); + + // 获取国际化语言 + // Get the locale + const getLocale = toRef(() => appStore.getProjectSetting.locale); + + // 获取是否显示主题切换按钮 + // Get whether to display the dark mode toggle button + const getShouldShowDarkModeToggle = toRef(() => appStore.getProjectSetting.shouldShowDarkModeToggle); + + // 获取配置按钮显示位置 + // Get the position of the setting button display + const getSettingButtonPosition = toRef(() => appStore.getProjectSetting.settingButtonPosition); + + // 获取权限模式 + // Get the permission mode + const getPermissionMode = toRef(() => appStore.getProjectSetting.permissionMode); + + // 获取权限缓存类型 + // Get the permission cache type + const getPermissionCacheType = toRef(() => appStore.getProjectSetting.permissionCacheType); + + // 获取会话超时处理方式 + // Get the session timeout processing method + const getSessionTimeoutProcessing = toRef(() => appStore.getProjectSetting.sessionTimeoutProcessing); + + // 获取主界面全屏显示,不显示菜单和顶部 + // Get whether to display the main interface in full screen, without menu and top bar + const getShouldShowFullContent = toRef(() => appStore.getProjectSetting.shouldShowFullContent); + + // 获取是否显示 logo + // Get whether to display the logo + const getShouldShowLogo = toRef(() => appStore.getProjectSetting.shouldShowLogo); + + // 获取是否显示全局底部 + // Get whether to display the global footer + const getShouldShowFooter = toRef(() => appStore.getProjectSetting.shouldShowFooter); + + // 获取页面布局是否启用 keep-alive + // Get whether to enable keep-alive for page layout + const getShouldOpenKeepAlive = toRef(() => appStore.getProjectSetting.shouldOpenKeepAlive); + + // 获取锁屏时间 + // Get the lock screen time + const getLockTime = toRef(() => appStore.getProjectSetting.lockTime); + + // 获取是否显示面包屑 + // Get whether to display the breadcrumb + const getShouldShowBreadCrumb = toRef(() => appStore.getProjectSetting.shouldShowBreadCrumb); + + // 获取是否显示面包屑图标 + // Get whether to display the breadcrumb icon + const getShouldShowBreadCrumbIcon = toRef(() => appStore.getProjectSetting.shouldShowBreadCrumbIcon); + + // 获取是否使用 error-handler-plugin + // Get whether to use the error-handler-plugin + const getShouldUseErrorHandle = toRef(() => appStore.getProjectSetting.shouldUseErrorHandle); + + // 获取是否开启返回顶部 + // Get whether to enable the back to top function + const getShouldUseOpenBackTop = toRef(() => appStore.getProjectSetting.shouldUseOpenBackTop); + + // 获取是否可以嵌入 iframe 页面 + // Get whether to embed iframe pages + const getCanEmbedIFramePage = toRef(() => appStore.getProjectSetting.canEmbedIFramePage); + + // 获取是否在切换界面时删除未关闭的消息并通知 + // Get whether to delete unclosed messages and notify when switching pages + const getShouldCloseMessageOnSwitch = toRef(() => appStore.getProjectSetting.shouldCloseMessageOnSwitch); + + // 获取是否在切换界面时取消已发送但未响应的 http 请求 + // Get whether to cancel sent but unresponsive http requests when switching pages + const getShouldRemoveAllHttpPending = toRef(() => appStore.getProjectSetting.shouldRemoveAllHttpPending); + + function getProjectSetting() { + return appStore.getProjectSetting; + } + function setProjectSetting(config: DeepPartial) { + appStore.setProjectSetting(config); + } + + return { + getProjectSetting, + setProjectSetting, + getShouldShowSettingButton, + getLocale, + getShouldShowDarkModeToggle, + getSettingButtonPosition, + getPermissionMode, + getPermissionCacheType, + getSessionTimeoutProcessing, + getShouldShowFullContent, + getShouldShowLogo, + getShouldShowFooter, + getShouldOpenKeepAlive, + getLockTime, + getShouldShowBreadCrumb, + getShouldShowBreadCrumbIcon, + getShouldUseErrorHandle, + getShouldUseOpenBackTop, + getCanEmbedIFramePage, + getShouldCloseMessageOnSwitch, + getShouldRemoveAllHttpPending, + }; +} diff --git a/apps/thin/src/composables/setting/useGlobSetting.ts b/apps/thin/src/composables/setting/useGlobSetting.ts new file mode 100644 index 00000000..27f14812 --- /dev/null +++ b/apps/thin/src/composables/setting/useGlobSetting.ts @@ -0,0 +1,7 @@ +import type { GlobConfig, GlobEnvConfig } from "@celeris/types"; +import { getAppGlobalConfig } from "@celeris/utils"; + +export function useGlobSetting(): Readonly { + const glob = getAppGlobalConfig(import.meta.env); + return glob as Readonly; +} diff --git a/apps/thin/src/composables/setting/useHeaderSetting.ts b/apps/thin/src/composables/setting/useHeaderSetting.ts new file mode 100644 index 00000000..67717d70 --- /dev/null +++ b/apps/thin/src/composables/setting/useHeaderSetting.ts @@ -0,0 +1,53 @@ +import type { HeaderSetting } from "@celeris/types"; +import { useAppStoreWithOut } from "~/store/modules/app"; + +export function useHeaderSetting() { + const appStore = useAppStoreWithOut(); + + // 获取是否显示网站头部 + // Get whether to show the website header + const getShouldShowHeader = computed(() => appStore.getHeaderSetting.shouldShow); + + // 获取是否显示全屏按钮 + // Get whether to show the full screen button + const getShouldShowFullScreen = computed(() => appStore.getHeaderSetting.shouldShowFullScreen); + + // 获取是否显示搜索 + // Get whether to show the search + const getShouldShowSearch = computed(() => appStore.getHeaderSetting.shouldShowSearch); + + // 获取是否显示通知 + // Get whether to show the notice + const getShouldShowNotice = computed(() => appStore.getHeaderSetting.shouldShowNotice); + + // 获取是否显示设置抽屉 + // Get whether to show the setting drawer + const getShouldShowSettingDrawer = computed(() => appStore.getHeaderSetting.shouldShowSettingDrawer); + + const setShouldShowSettingDrawer = (shouldShowSettingDrawer: boolean) => { + appStore.setHeaderSetting({ shouldShowSettingDrawer }); + }; + + const toggleShouldShowSettingDrawer = () => { + setShouldShowSettingDrawer(!getShouldShowSettingDrawer.value); + }; + + function getHeaderSetting() { + return appStore.getHeaderSetting; + } + function setHeaderSetting(headerSetting: Partial) { + appStore.setHeaderSetting(headerSetting); + } + + return { + getHeaderSetting, + setHeaderSetting, + getShouldShowHeader, + getShouldShowFullScreen, + getShouldShowSearch, + getShouldShowNotice, + getShouldShowSettingDrawer, + setShouldShowSettingDrawer, + toggleShouldShowSettingDrawer, + }; +} diff --git a/apps/thin/src/composables/setting/useMenuSetting.ts b/apps/thin/src/composables/setting/useMenuSetting.ts new file mode 100644 index 00000000..8e02d2ef --- /dev/null +++ b/apps/thin/src/composables/setting/useMenuSetting.ts @@ -0,0 +1,29 @@ +import type { MenuSetting } from "@celeris/types"; +import { useAppStoreWithOut } from "~/store/modules/app"; + +export function useMenuSetting() { + const appStore = useAppStoreWithOut(); + + const getCollapsed = computed(() => appStore.getMenuSetting.collapsed); + + function getMenuSetting() { + return appStore.getMenuSetting; + } + + // Set menu configuration + function setMenuSetting(menuSetting: Partial): void { + appStore.setProjectSetting({ menuSetting }); + } + + function toggleCollapsed() { + setMenuSetting({ + collapsed: !unref(getCollapsed), + }); + } + return { + getMenuSetting, + setMenuSetting, + getCollapsed, + toggleCollapsed, + }; +} diff --git a/apps/thin/src/composables/setting/usePermissionSetting.ts b/apps/thin/src/composables/setting/usePermissionSetting.ts new file mode 100644 index 00000000..3e00f59e --- /dev/null +++ b/apps/thin/src/composables/setting/usePermissionSetting.ts @@ -0,0 +1,121 @@ +import type { RoleConstants } from "@celeris/constants"; +import { PermissionModeConstants } from "@celeris/constants"; +import { intersection, isArray } from "@celeris/utils"; +import type { RouteRecordRaw } from "vue-router"; +import { resetRouter, router } from "~/router"; +import { DEFAULT_PROJECT_SETTING } from "~/setting/projectSetting"; +import { useAppStoreWithOut } from "~/store/modules/app"; +import { usePermissionStoreWithOut } from "~/store/modules/permission"; +import { useUserStoreWithOut } from "~/store/modules/user"; + +export function useAppPermission() { + const userStore = useUserStoreWithOut(); + const appStore = useAppStoreWithOut(); + const permissionStore = usePermissionStoreWithOut(); + + const getPermissionMode = toRef(() => appStore.getProjectSetting.permissionMode); + + const isBackendPermissionMode = toRef(() => getPermissionMode.value === PermissionModeConstants.BACKEND); + + const isRouteMappingPermissionMode = toRef(() => getPermissionMode.value === PermissionModeConstants.ROUTE_MAPPING); + + const isRolePermissionMode = toRef(() => getPermissionMode.value === PermissionModeConstants.ROLE); + + /** + * Toggle permission mode function. + * 切换权限模式函数。 + * + * Changes the permission mode between backend and route mapping. + * 在后端和路由映射之间切换权限模式。 + * + */ + function togglePermissionMode() { + appStore.setProjectSetting({ + permissionMode: + appStore.projectSetting?.permissionMode === PermissionModeConstants.BACKEND + ? PermissionModeConstants.ROUTE_MAPPING + : PermissionModeConstants.BACKEND, + }); + location.reload(); + } + + /** + * Reset and regain authority resource information + * 重置和重新获得权限资源信息 + * @returns Promise + */ + async function resume() { + resetRouter(); + const routes: RouteRecordRaw[] = await permissionStore.buildRoutesAction(); + routes.forEach((route: RouteRecordRaw) => { + router.addRoute(route); + }); + permissionStore.setLastMenuBuildTime(); + } + + /** + * Determine whether there is permission + * 判断是否有权限 + * @param permission RoleConstants | RoleConstants[] | string | string[] permission value. 权限值 + * @param defaultValue boolean default value. 默认值 + * @returns boolean whether there is permission + * 返回值是否有权限 + */ + function hasPermission(permission?: RoleConstants | RoleConstants[] | string | string[], defaultValue = false): boolean { + if (!permission) { + return defaultValue; + } + + const permMode = DEFAULT_PROJECT_SETTING.permissionMode; + + if ([PermissionModeConstants.ROUTE_MAPPING, PermissionModeConstants.ROLE].includes(permMode)) { + if (!isArray(permission)) { + return userStore.getRoleList.includes(permission as RoleConstants); + } + return (intersection(permission, userStore.getRoleList)).length > 0; + } + + if (PermissionModeConstants.BACKEND === permMode) { + const allCodeList = permissionStore.getPermissionCodes as string[]; + if (!isArray(permission)) { + return allCodeList.includes(permission); + } + return (intersection(permission, allCodeList)).length > 0; + } + return defaultValue; + } + + /** + * Change the roles of the current user. + * 更改当前用户的角色。 + * @param roles RoleConstants | RoleConstants[] The roles to be assigned to the user. 要分配给用户的角色。 + * @returns Promise + */ + async function changeRole(roles: RoleConstants | RoleConstants[]): Promise { + if (DEFAULT_PROJECT_SETTING.permissionMode !== PermissionModeConstants.ROUTE_MAPPING) { + throw new Error( + "Please switch to ROUTE_MAPPING mode in the configuration before performing this operation.", + ); + } + + if (!isArray(roles)) { + roles = [roles]; + } + userStore.setRoleList(roles); + await resume(); + } + + async function refreshMenu() { + await resume(); + } + return { + getPermissionMode, + isBackendPermissionMode, + isRouteMappingPermissionMode, + isRolePermissionMode, + changeRole, + hasPermission, + togglePermissionMode, + refreshMenu, + }; +} diff --git a/apps/thin/src/composables/setting/useThemeSetting.ts b/apps/thin/src/composables/setting/useThemeSetting.ts new file mode 100644 index 00000000..b3bed525 --- /dev/null +++ b/apps/thin/src/composables/setting/useThemeSetting.ts @@ -0,0 +1,70 @@ +import { useDesignStoreWithOut } from "~/store/modules/design"; + +export function useThemeSetting() { + const designStore = useDesignStoreWithOut(); + + // 获取主题配置 + // get theme setting + const getThemeSetting = () => designStore.getThemeSetting; + + // 设置主题配置 + // set theme setting + const setThemeSetting = themeSetting => designStore.setThemeSetting(themeSetting); + + // 获取Naive UI 预设主题 + // get Naive UI preset theme + const getNaiveUIPresetTheme = toRef(() => designStore.getNaiveUIPresetTheme); + + // 获取Naive UI 自定义主题 + // get Naive UI custom theme + const getNaiveUICustomTheme = toRef(() => designStore.getNaiveUICustomTheme); + + // 获取暗黑模式 + // get dark mode + const getDarkMode = toRef(() => designStore.getDarkMode); + + // 获取色弱模式 + // get color weak mode + const getColorWeakMode = toRef(() => designStore.getColorWeakMode); + + // 获取灰色模式 + // get gray mode + const getGrayMode = toRef(() => designStore.getGrayMode); + + // 获取跟随系统主题 + // get follow system theme + const getFollowSystemTheme = toRef(() => designStore.getFollowSystemTheme); + + // 获取主题颜色 + // get theme color + const getThemeColor = toRef(() => designStore.getThemeColor); + + const setDarkMode = darkMode => designStore.setDarkMode(darkMode); + + const setColorWeakMode = colorWeakMode => designStore.setColorWeakMode(colorWeakMode); + + const setGrayMode = grayMode => designStore.setGrayMode(grayMode); + + const setFollowSystemTheme = followSystemTheme => designStore.setFollowSystemTheme(followSystemTheme); + + const setThemeColor = themeColor => designStore.setThemeColor(themeColor); + + const resetDesignState = () => designStore.resetDesignState(); + return { + getThemeSetting, + setThemeSetting, + getNaiveUIPresetTheme, + getNaiveUICustomTheme, + getDarkMode, + getColorWeakMode, + getGrayMode, + getFollowSystemTheme, + getThemeColor, + setDarkMode, + setColorWeakMode, + setGrayMode, + setFollowSystemTheme, + setThemeColor, + resetDesignState, + }; +} diff --git a/apps/thin/src/composables/setting/useTransitionSetting.ts b/apps/thin/src/composables/setting/useTransitionSetting.ts new file mode 100644 index 00000000..e09d90a9 --- /dev/null +++ b/apps/thin/src/composables/setting/useTransitionSetting.ts @@ -0,0 +1,50 @@ +import type { TransitionSetting } from "@celeris/types"; +import { useAppStoreWithOut } from "~/store/modules/app"; + +export function useTransitionSetting() { + const appStore = useAppStoreWithOut(); + + const getShouldEnableTransition = toRef(() => appStore.getTransitionSetting.shouldEnable); + + const getShouldOpenNProgress = toRef(() => appStore.getTransitionSetting.shouldOpenNProgress); + + const getShouldOpenPageLoading = toRef(() => appStore.getTransitionSetting.shouldOpenPageLoading); + + const getRouterBasicTransition = toRef(() => appStore.getTransitionSetting.routerBasicTransition); + + const setRouterBasicTransition = (routerBasicTransition: TransitionSetting["routerBasicTransition"]) => { + appStore.setProjectSetting({ transitionSetting: { routerBasicTransition } }); + }; + + const setShouldEnableTransition = (shouldEnable: TransitionSetting["shouldEnable"]) => { + appStore.setProjectSetting({ transitionSetting: { shouldEnable } }); + }; + + const setShouldOpenNProgress = (shouldOpenNProgress: TransitionSetting["shouldOpenNProgress"]) => { + appStore.setProjectSetting({ transitionSetting: { shouldOpenNProgress } }); + }; + + const setShouldOpenPageLoading = (shouldOpenPageLoading: TransitionSetting["shouldOpenPageLoading"]) => { + appStore.setProjectSetting({ transitionSetting: { shouldOpenPageLoading } }); + }; + + function getTransitionSetting() { + return appStore.getTransitionSetting; + } + function setTransitionSetting(transitionSetting: Partial) { + appStore.setProjectSetting({ transitionSetting }); + } + return { + getTransitionSetting, + setTransitionSetting, + + getShouldEnableTransition, + setShouldEnableTransition, + getShouldOpenNProgress, + setShouldOpenNProgress, + getShouldOpenPageLoading, + setShouldOpenPageLoading, + getRouterBasicTransition, + setRouterBasicTransition, + }; +} diff --git a/apps/thin/src/composables/useChartOption.ts b/apps/thin/src/composables/useChartOption.ts new file mode 100644 index 00000000..403206e6 --- /dev/null +++ b/apps/thin/src/composables/useChartOption.ts @@ -0,0 +1,33 @@ +import type { ComputedRef } from "vue"; +import { computed } from "vue"; +import type { EChartsOption } from "echarts"; + +// Define function type +interface ChartOptionsGenerator { + (isDark: boolean): EChartsOption; +} + +// Define return type +interface UseChartOptionReturn { + chartOption: ComputedRef; +} + +// 根据源选项生成图表选项 +// Generate chart options based on source options +export function useChartOption(generateSourceOptions: ChartOptionsGenerator): UseChartOptionReturn { + const { getDarkMode: isDark } = useThemeSetting(); + // 生成图表选项 + // Generate chart options + const generateChartOptions = (): EChartsOption => { + // TODO: echarts themes + // ECharts可以使用主题构建器,但这里未使用 + // ECharts can use theme builders, but it is not used here + return generateSourceOptions(isDark.value); + }; + + // 返回计算属性 + // Return computed property + return { + chartOption: computed(() => generateChartOptions()), + }; +} diff --git a/apps/thin/src/composables/useNaiveUIConfigProvider.ts b/apps/thin/src/composables/useNaiveUIConfigProvider.ts new file mode 100644 index 00000000..62b982c5 --- /dev/null +++ b/apps/thin/src/composables/useNaiveUIConfigProvider.ts @@ -0,0 +1,22 @@ +import { dateZhCN, zhCN } from "naive-ui"; +import { useAppSetting, useThemeSetting } from "~/composables/setting"; +import { designNamespace, designPrefixCls } from "~/setting/designSetting"; + +// Naive UI Config Provider +export function useNaiveUIConfigProvider() { + const { getNaiveUIPresetTheme, getNaiveUICustomTheme } = useThemeSetting(); + const { getLocale } = useAppSetting(); + const configProviderProps = toRef({ + "cls-prefix": designPrefixCls, + "theme": getNaiveUIPresetTheme, + "theme-overrides": getNaiveUICustomTheme, + "namespace": designNamespace, + "locale": getLocale.value === "zh" ? zhCN : null, + "date-locale": getLocale.value === "zh" ? dateZhCN : null, + "inline-theme-disabled": true, + }); + + return { + configProviderProps, + }; +} diff --git a/apps/thin/src/composables/useSearchDialog.ts b/apps/thin/src/composables/useSearchDialog.ts new file mode 100644 index 00000000..85481483 --- /dev/null +++ b/apps/thin/src/composables/useSearchDialog.ts @@ -0,0 +1,16 @@ +import { ref } from "vue"; +import { isWindows } from "@celeris/utils"; + +const listener = ref(); +export function useSearchDialog() { + const commandIcon = ref(isWindows() ? "CTRL" : "⌘"); + return { + commandIcon, + trigger: (cb: () => void): void => { + listener.value = cb; + }, + open: (): void => { + listener.value && listener.value(); + }, + }; +} diff --git a/apps/thin/src/directives/permission.ts b/apps/thin/src/directives/permission.ts new file mode 100644 index 00000000..89347c02 --- /dev/null +++ b/apps/thin/src/directives/permission.ts @@ -0,0 +1,32 @@ +/** + * Global authority directive + * Used for fine-grained control of component permissions + * @Example v-auth="RoleEnum.ADMIN" + */ +import type { App, Directive, DirectiveBinding } from "vue"; + +function isAuth(el: Element, binding: any) { + const { hasPermission } = useAppPermission(); + + const value = binding.value; + if (!value) { + return; + } + if (!hasPermission(value)) { + el.parentNode?.removeChild(el); + } +} + +function mounted(el: Element, binding: DirectiveBinding) { + isAuth(el, binding); +} + +const authDirective: Directive = { + mounted, +}; + +export function setupPermissionDirective(app: App) { + app.directive("auth", authDirective); +} + +export default authDirective; diff --git a/apps/thin/src/layouts/content/index.vue b/apps/thin/src/layouts/content/index.vue new file mode 100644 index 00000000..a25881e7 --- /dev/null +++ b/apps/thin/src/layouts/content/index.vue @@ -0,0 +1,26 @@ + + + + + diff --git a/apps/thin/src/layouts/footer/index.vue b/apps/thin/src/layouts/footer/index.vue new file mode 100644 index 00000000..f5dd1299 --- /dev/null +++ b/apps/thin/src/layouts/footer/index.vue @@ -0,0 +1,11 @@ + + + diff --git a/apps/thin/src/layouts/header/components/Breadcrumb.vue b/apps/thin/src/layouts/header/components/Breadcrumb.vue new file mode 100644 index 00000000..4ba0a789 --- /dev/null +++ b/apps/thin/src/layouts/header/components/Breadcrumb.vue @@ -0,0 +1,89 @@ + + + + + diff --git a/apps/thin/src/layouts/header/components/CollapseButton.vue b/apps/thin/src/layouts/header/components/CollapseButton.vue new file mode 100644 index 00000000..e995b19b --- /dev/null +++ b/apps/thin/src/layouts/header/components/CollapseButton.vue @@ -0,0 +1,12 @@ + + + diff --git a/apps/thin/src/layouts/header/components/FullScreenButton.vue b/apps/thin/src/layouts/header/components/FullScreenButton.vue new file mode 100644 index 00000000..effa8970 --- /dev/null +++ b/apps/thin/src/layouts/header/components/FullScreenButton.vue @@ -0,0 +1,14 @@ + + + + + diff --git a/apps/thin/src/layouts/header/components/LocaleSwitcher.vue b/apps/thin/src/layouts/header/components/LocaleSwitcher.vue new file mode 100644 index 00000000..e882ce3c --- /dev/null +++ b/apps/thin/src/layouts/header/components/LocaleSwitcher.vue @@ -0,0 +1,31 @@ + + + + + diff --git a/apps/thin/src/layouts/header/components/SearchAnyWhere.vue b/apps/thin/src/layouts/header/components/SearchAnyWhere.vue new file mode 100644 index 00000000..2053b132 --- /dev/null +++ b/apps/thin/src/layouts/header/components/SearchAnyWhere.vue @@ -0,0 +1,70 @@ + + + + + diff --git a/apps/thin/src/layouts/header/components/UserInfoButton.vue b/apps/thin/src/layouts/header/components/UserInfoButton.vue new file mode 100644 index 00000000..2429d6ad --- /dev/null +++ b/apps/thin/src/layouts/header/components/UserInfoButton.vue @@ -0,0 +1,66 @@ + + + + + diff --git a/apps/thin/src/layouts/header/index.vue b/apps/thin/src/layouts/header/index.vue new file mode 100644 index 00000000..e5f13a0b --- /dev/null +++ b/apps/thin/src/layouts/header/index.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/apps/thin/src/layouts/index.vue b/apps/thin/src/layouts/index.vue new file mode 100644 index 00000000..824160d2 --- /dev/null +++ b/apps/thin/src/layouts/index.vue @@ -0,0 +1,36 @@ + + + + + diff --git a/apps/thin/src/layouts/setting/components/SettingButton.vue b/apps/thin/src/layouts/setting/components/SettingButton.vue new file mode 100644 index 00000000..1818e6ef --- /dev/null +++ b/apps/thin/src/layouts/setting/components/SettingButton.vue @@ -0,0 +1,18 @@ + + + + + diff --git a/apps/thin/src/layouts/setting/components/SettingDrawer/components/DarkMode/index.vue b/apps/thin/src/layouts/setting/components/SettingDrawer/components/DarkMode/index.vue new file mode 100644 index 00000000..6892b1bf --- /dev/null +++ b/apps/thin/src/layouts/setting/components/SettingDrawer/components/DarkMode/index.vue @@ -0,0 +1,39 @@ + + + + + diff --git a/apps/thin/src/layouts/setting/components/SettingDrawer/components/SettingMenu/index.vue b/apps/thin/src/layouts/setting/components/SettingDrawer/components/SettingMenu/index.vue new file mode 100644 index 00000000..be8b6c52 --- /dev/null +++ b/apps/thin/src/layouts/setting/components/SettingDrawer/components/SettingMenu/index.vue @@ -0,0 +1,20 @@ + + + + + diff --git a/apps/thin/src/layouts/setting/components/SettingDrawer/components/SettingTransition/index.vue b/apps/thin/src/layouts/setting/components/SettingDrawer/components/SettingTransition/index.vue new file mode 100644 index 00000000..6d9dbe2e --- /dev/null +++ b/apps/thin/src/layouts/setting/components/SettingDrawer/components/SettingTransition/index.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/apps/thin/src/layouts/setting/components/SettingDrawer/components/ThemeBackup/index.vue b/apps/thin/src/layouts/setting/components/SettingDrawer/components/ThemeBackup/index.vue new file mode 100644 index 00000000..85a5b1c4 --- /dev/null +++ b/apps/thin/src/layouts/setting/components/SettingDrawer/components/ThemeBackup/index.vue @@ -0,0 +1,42 @@ + + + + + diff --git a/apps/thin/src/layouts/setting/components/SettingDrawer/components/ThemeColor/components/ColorCheckbox.vue b/apps/thin/src/layouts/setting/components/SettingDrawer/components/ThemeColor/components/ColorCheckbox.vue new file mode 100644 index 00000000..ce25e3d8 --- /dev/null +++ b/apps/thin/src/layouts/setting/components/SettingDrawer/components/ThemeColor/components/ColorCheckbox.vue @@ -0,0 +1,39 @@ + + + + + diff --git a/apps/thin/src/layouts/setting/components/SettingDrawer/components/ThemeColor/components/index.ts b/apps/thin/src/layouts/setting/components/SettingDrawer/components/ThemeColor/components/index.ts new file mode 100644 index 00000000..9488f28d --- /dev/null +++ b/apps/thin/src/layouts/setting/components/SettingDrawer/components/ThemeColor/components/index.ts @@ -0,0 +1,3 @@ +import ColorCheckbox from "./ColorCheckbox.vue"; + +export { ColorCheckbox }; diff --git a/apps/thin/src/layouts/setting/components/SettingDrawer/components/ThemeColor/index.vue b/apps/thin/src/layouts/setting/components/SettingDrawer/components/ThemeColor/index.vue new file mode 100644 index 00000000..0258991c --- /dev/null +++ b/apps/thin/src/layouts/setting/components/SettingDrawer/components/ThemeColor/index.vue @@ -0,0 +1,25 @@ + + + + + diff --git a/apps/thin/src/layouts/setting/components/SettingDrawer/components/index.ts b/apps/thin/src/layouts/setting/components/SettingDrawer/components/index.ts new file mode 100644 index 00000000..959415bd --- /dev/null +++ b/apps/thin/src/layouts/setting/components/SettingDrawer/components/index.ts @@ -0,0 +1,7 @@ +import DarkMode from "./DarkMode/index.vue"; +import SettingMenu from "./SettingMenu/index.vue"; +import SettingTransition from "./SettingTransition/index.vue"; +import ThemeBackup from "./ThemeBackup/index.vue"; +import ThemeColor from "./ThemeColor/index.vue"; + +export { DarkMode, SettingMenu, SettingTransition, ThemeBackup, ThemeColor }; diff --git a/apps/thin/src/layouts/setting/components/SettingDrawer/index.vue b/apps/thin/src/layouts/setting/components/SettingDrawer/index.vue new file mode 100644 index 00000000..8e9af143 --- /dev/null +++ b/apps/thin/src/layouts/setting/components/SettingDrawer/index.vue @@ -0,0 +1,28 @@ + + + + + diff --git a/apps/thin/src/layouts/setting/index.vue b/apps/thin/src/layouts/setting/index.vue new file mode 100644 index 00000000..099f1b5f --- /dev/null +++ b/apps/thin/src/layouts/setting/index.vue @@ -0,0 +1,17 @@ + + + + + diff --git a/apps/thin/src/layouts/sidebar/components/Menu.vue b/apps/thin/src/layouts/sidebar/components/Menu.vue new file mode 100644 index 00000000..e332e178 --- /dev/null +++ b/apps/thin/src/layouts/sidebar/components/Menu.vue @@ -0,0 +1,103 @@ + + + + + diff --git a/apps/thin/src/layouts/sidebar/components/SidebarFooter.vue b/apps/thin/src/layouts/sidebar/components/SidebarFooter.vue new file mode 100644 index 00000000..9316d9ed --- /dev/null +++ b/apps/thin/src/layouts/sidebar/components/SidebarFooter.vue @@ -0,0 +1,20 @@ + + + + + diff --git a/apps/thin/src/layouts/sidebar/components/SidebarHeader.vue b/apps/thin/src/layouts/sidebar/components/SidebarHeader.vue new file mode 100644 index 00000000..ebfc4c77 --- /dev/null +++ b/apps/thin/src/layouts/sidebar/components/SidebarHeader.vue @@ -0,0 +1,19 @@ + + + + + diff --git a/apps/thin/src/layouts/sidebar/index.vue b/apps/thin/src/layouts/sidebar/index.vue new file mode 100644 index 00000000..2724973b --- /dev/null +++ b/apps/thin/src/layouts/sidebar/index.vue @@ -0,0 +1,34 @@ + + + + + diff --git a/apps/thin/src/layouts/transition.ts b/apps/thin/src/layouts/transition.ts new file mode 100644 index 00000000..89a9ebe2 --- /dev/null +++ b/apps/thin/src/layouts/transition.ts @@ -0,0 +1,19 @@ +import type { RouteLocationNormalizedLoaded } from "vue-router"; +import { useTransitionSetting } from "~/composables"; + +interface Context { + route: RouteLocationNormalizedLoaded; +} + +interface TransitionOptions { + enableTransition: boolean; +} + +export function getTransitionName({ route }: Context, { enableTransition }: TransitionOptions): string | undefined { + const { getRouterBasicTransition, getShouldEnableTransition } = useTransitionSetting(); + if (!enableTransition || !toValue(getShouldEnableTransition)) { + return undefined; + } + + return (route.meta.transitionName as string) || toValue(getRouterBasicTransition); +} diff --git a/apps/thin/src/locales/en.json b/apps/thin/src/locales/en.json new file mode 100644 index 00000000..98751b09 --- /dev/null +++ b/apps/thin/src/locales/en.json @@ -0,0 +1,250 @@ +{ + "routes": { + "components": { + "components": "Component Example", + "table": "Table Component", + "headlessTable": "Headless Table", + "headlessTableBasic": "Basic Table", + "headlessTablePagination": "Pagination Table" + }, + "chat": { + "chat": "Chat" + }, + "profile": { + "profile": "Profile" + }, + "design": { + "design": "Design", + "palette": "Palette", + "typography": "Typography" + }, + "dashboard": { + "dashboard": "Dashboard" + }, + "directives": { + "directives": "Directive Examples", + "permission": "Permission Directive", + "copy": "Copy Directive", + "ripple": "Ripple Directive" + }, + "iframe": { + "iframe": "Embedded Webpage", + "githubInternal": "GitHub (Embedded)", + "GitHubExternal": "GitHub (External)", + "viteInternal": "Vite Documentation (Embedded)", + "ViteExternal": "Vite Documentation (External)" + }, + "permission": { + "permission": "Permission Test", + "authPageA": "Test Page A", + "authPageB": "Test Page B", + "frontend": "Frontend-based", + "backend": "Backend-based", + "pageAuth": "Page Permissions", + "buttonAuth": "Button Permissions", + "role": "Role Permissions", + "directive": "Directive Permissions" + }, + "result": { + "result": "Result Page", + "success": "Success Page", + "fail": "Fail Page" + } + }, + "layouts": { + "header": { + "toggleCollapsed": "Toggle Menu", + "toggleFullScreen": "Toggle Fullscreen", + "switchLocale": "Switch Language", + "settingDrawer": "Settings Drawer", + "openSettingDrawer": "Open Settings Drawer", + "projectSetting": "Project Settings", + "darkMode": "Dark Mode", + "followSystem": "Follow System", + "systemDefault": "System Default", + "systemTheme": "System Theme", + "themeMode": "Theme Mode", + "lightMode": "Light Mode", + "colorWeak": "Color Weak Mode", + "themeConfig": { + "title": "Theme Configuration", + "copyConfigButton": "Copy Current Configuration", + "resetConfigButton": "Reset Current Configuration", + "message": { + "copyConfigSuccess": "Configuration copied successfully!", + "resetConfigSuccess": "Configuration reset successfully!" + } + }, + "transitionSetting": { + "title": "Animation Settings", + "enableTransition": "Enable Animation", + "enableProgressBar": "Enable Progress Bar", + "enablePageLoadingTransition": "Enable Page Loading Animation", + "routeTransition": "Route Transition" + } + }, + "userInfo": { + "userInformation": "User Information", + "greeting": "Hello", + "rolesList": "Role List: {roles}", + "logoutButton": "Logout" + }, + "logoutConfirmation": { + "title": "Warning", + "content": "Are you sure you want to log out?", + "positiveText": "Logout", + "negativeText": "Cancel", + "onNegativeClickMessage": "Logout canceled", + "onPositiveClickMessage": "Logout successful" + } + }, + "searchDialog": { + "searchPlaceholder": "Search", + "noResultsFound": "Sorry, no results found for { search }", + "toSelectTooltip": "to select", + "toNavigateTooltip": "to navigate", + "applications": "Applications", + "chatBot": "ChatBot", + "action": "Action", + "actions": "Actions", + "shortcut": "Shortcut", + "go": "Go to " + }, + "page": { + "login": { + "title": "Login", + "form": { + "username": { + "label": "Username", + "placeholder": "Enter your username", + "error": "Username cannot be empty" + }, + "password": { + "label": "Password", + "placeholder": "Enter your password", + "error": "Password cannot be empty" + }, + "confirmPassword": { + "label": "Confirm Password", + "placeholder": "Enter your password", + "error": "Confirm password cannot be empty", + "validator": "Password is not same!" + }, + "forgotPassword": { + "label": "Phone Number", + "placeholder": "Example: 13812345678", + "requiredError": "Phone number is required", + "invalidFormatError": "Invalid phone number format" + }, + "socialButtons": { + "signInWithQQ": "Sign in with QQ", + "signInWithWeChat": "Sign in with WeChat" + }, + "signText": { + "signIn": "Don't you have an account?", + "forgotPassword": "Back to Sign in", + "signUp": "Do you have an account?" + }, + "welcomeBackTitle": "Welcome Back", + "helloTitle": "Hello", + "forgotPasswordTitle": "Forgot Password", + "greetingText": "Celeris Web is a highly performant and customizable front-end development template built with Vue 3, Vite, and TypeScript.", + "sendResetLinkButton": "Send Reset Link", + "resetLinkSentMessage": "Reset Link sent", + "signUp": "Sign up", + "backToSignIn": "Back to Sign in", + "signIn": "Sign in", + "remember": "Remember me", + "loginButton": "Sign in", + "registerButton": "Create an account", + "forgetPassword": "Forgot password", + "incorrectAccountOrPassword": "Incorrect account or password!" + }, + "notification": { + "loginSuccessMessage": "Login successful", + "welcomeBackMessage": "Welcome back, {username}!" + } + }, + "copyDirective": { + "copy": "Copy", + "copyDirective": "Copy Directive Example", + "copyPlaceholder": "Please enter the content to copy", + "copySuccess": "Copy successful", + "copyError": "Copy failed" + }, + "rippleDirective": { + "ripple": "Ripple", + "rippleDirective": "Ripple Directive Example", + "description1": "Ripples are state layers used to communicate the status of a component or interactive element.", + "description2": "A state layer is a semi-transparent covering on an element that indicates its state." + }, + "permission": { + "permissionMode": { + "currentMode": "Current Permission Mode", + "backendMode": "Backend Permission Mode", + "frontendMode": "Frontend Role Permission Mode", + "toggleMode": "Toggle Permission Mode" + }, + "pageTitles": { + "frontend": "Frontend Permission Example", + "backend": "Backend Permission Example", + "button": "Button Permission Control" + }, + "roleButtonText": "Visible with {role} Role", + "codeButtonText": "Visible with [{code}] Code", + "currentPermissionMode": "Current Permission Mode", + "currentRole": "Current Role", + "currentCode": "Current Code", + "clickToSeeButtonChange": "Click to see button changes", + "clickToSeeLeftMenuChange": "Click to see left menu changes", + "frontendPermissionSwitchTitle": "Permission Switching (Please switch permission mode to Frontend Role mode first)", + "backendPermissionSwitchTitle": "Permission Switching (Please switch permission mode to Backend Role mode first)", + "componentWayTitle": "Component-based Permission Check (You can register it globally if needed)", + "functionWayTitle": "Function-based Permission Check (Suitable for filtering within functions)", + "directiveWayTitle": "Directive-based Permission Check (This method cannot dynamically modify permissions)", + "backendLeftMenuChangeTitle": "Click to see left menu changes (Must be in Backend Role mode to test the functionality displayed on this page)" + }, + "headlessTable": { + "pageTitles": { + "basic": "Basic Table" + } + }, + "result": { + "status": { + "error": "Error", + "success": "Success" + }, + "failPage": { + "title": "Error Sending Content", + "subTitle": "Sorry, there was a problem sending the content.", + "buttons": { + "home": "Return to Home", + "back": "Go Back" + }, + "errorHeader": "There might be the following issues when sending content:", + "networkIssue": "Network connection problem", + "checkNetwork": "Check network >", + "messageTooLong": "Message is too long, please simplify", + "viewHelp": "View help >" + }, + "successPage": { + "title": "Operation Successful", + "subTitle": "Content generated by ChatGPT has been successfully created.", + "buttons": { + "home": "Return to Home" + }, + "contentHeader": "AIGC Generated Content:", + "generatedTimeLabel": "Generated Time", + "generatorLabel": "Generator", + "generatedContent": "Generated content will be displayed here", + "contentLabel": "Content", + "step1": "Input Content", + "step2": "Generating", + "step2Content": "ChatGPT is generating content, please wait a moment.", + "step3": "Under Review", + "step3Content": "Generated content is under review and will be approved shortly.", + "step4": "Completed" + } + } + } +} diff --git a/apps/thin/src/locales/zh.json b/apps/thin/src/locales/zh.json new file mode 100644 index 00000000..44c550c7 --- /dev/null +++ b/apps/thin/src/locales/zh.json @@ -0,0 +1,251 @@ +{ + "routes": { + "components": { + "components": "组件示例", + "table": "表格组件", + "headlessTable": "Headless 表格", + "headlessTableBasic": "基础表格", + "headlessTablePagination": "分页表格" + }, + "chat": { + "chat": "Chat" + }, + "profile": { + "profile": "个人资料" + }, + "design": { + "design": "设计", + "palette": "调色板", + "typography": "汉字排版" + }, + "dashboard": { + "dashboard": "仪表盘" + }, + "directives": { + "directives": "指令示例", + "permission": "权限指令", + "copy": "复制指令", + "ripple": "涟漪指令" + }, + "iframe": { + "iframe": "内嵌网页", + "githubInternal": "GitHub 仓库(内嵌)", + "GitHubExternal": "GitHub 仓库(外链)", + "viteInternal": "Vite 中文文档 (内嵌)", + "ViteExternal": "Vite 官方文档 (外链)" + }, + "permission": { + "permission": "权限测试页", + "authPageA": "权限测试页A", + "authPageB": "权限测试页B", + "frontend": "基于前端权限", + "backend": "基于后台权限", + "pageAuth": "页面权限", + "buttonAuth": "按钮权限", + "role": "角色权限", + "directive": "指令权限" + }, + "result": { + "result": "结果页", + "success": "成功页", + "fail": "失败页" + } + }, + "layouts": { + "header": { + "toggleCollapsed": "折叠菜单", + "toggleFullScreen": "切换全屏", + "switchLocale": "切换语言", + "settingDrawer": "设置抽屉", + "openSettingDrawer": "打开设置抽屉", + "projectSetting": "项目设置", + "darkMode": "深色主题", + "followSystem": "跟随系统", + "systemDefault": "系统默认", + "systemTheme": "系统主题", + "themeMode": "主题模式", + "lightMode": "浅色主题", + "colorWeak": "色弱模式", + "themeConfig": { + "title": "主题配置", + "copyConfigButton": "拷贝当前配置", + "resetConfigButton": "重置当前配置", + "message": { + "copyConfigSuccess": "拷贝配置成功!", + "resetConfigSuccess": "重置配置成功!" + } + }, + "transitionSetting": { + "title": "动画设置", + "enableTransition": "开启动画", + "enableProgressBar": "开启进度条", + "enablePageLoadingTransition": "开启页面加载动画", + "routeTransition": "切换路由动画" + } + }, + "userInfo": { + "userInformation": "用户信息", + "greeting": "你好", + "rolesList": "角色列表:{roles}", + "logoutButton": "退出登录" + }, + "logoutConfirmation": { + "title": "警告", + "content": "您确定要退出登录吗?", + "positiveText": "退出登录", + "negativeText": "取消", + "onNegativeClickMessage": "取消退出登录", + "onPositiveClickMessage": "退出登录成功" + } + }, + "searchDialog": { + "searchPlaceholder": "搜索", + "noResultsFound": "抱歉,未找到符合 { search } 的结果", + "toSelectTooltip": "选择", + "toNavigateTooltip": "导航", + "applications": "应用程序", + "chatBot": "ChatBot", + "actions": "操作列表", + "action": "操作", + "shortcut": "快捷方式", + "go": "前往" + }, + "page": { + "login": { + "title": "登录", + "form": { + "username": { + "label": "用户名", + "placeholder": "请输入用户名", + "error": "用户名不能为空" + }, + "password": { + "label": "密码", + "placeholder": "请输入密码", + "error": "密码不能为空" + }, + "confirmPassword": { + "label": "确认密码", + "placeholder": "请输入密码", + "error": "确认密码不能为空", + "validator": "两次密码不一致!" + }, + "forgotPassword": { + "label": "手机号码", + "placeholder": "示例:15912345678", + "requiredError": "手机号码不能为空", + "invalidFormatError": "无效的手机号码格式" + }, + "socialButtons": { + "signInWithQQ": "使用 QQ 登录", + "signInWithWeChat": "使用微信登录" + }, + "signText": { + "signIn": "还没有账号吗?", + "forgotPassword": "返回登录", + "signUp": "已经有账号了吗?" + }, + "welcomeBackTitle": "欢迎回来", + "helloTitle": "你好", + "forgotPasswordTitle": "忘记密码", + "greetingText": "Celeris Web 是一个使用 Vue 3、Vite 和 TypeScript 构建的高性能、可定制的前端开发模板。", + "sendResetLinkButton": "发送重置链接", + "resetLinkSentMessage": "重置链接已发送", + "signUp": "注册", + "backToSignIn": "返回登录", + "signIn": "登录", + "remember": "记住我", + "loginButton": "登录", + "registerButton": "注册", + "forgetPassword": "忘记密码", + "incorrectAccountOrPassword": "账号或密码不正确!" + }, + "notification": { + "loginSuccessMessage": "登录成功", + "welcomeBackMessage": "欢迎回来,{username}!" + } + }, + "copyDirective": { + "copy": "复制", + "copyDirective": "复制指令示例", + "copyPlaceholder": "请输入要复制的内容", + "copySuccess": "复制成功", + "copyError": "复制失败" + }, + "rippleDirective": { + "ripple": "涟漪", + "rippleDirective": "涟漪指令示例", + "description1": "涟漪是用于传达组件或交互元素状态的状态图层。", + "description2": "状态图层是放置在元素上的半透明覆盖层,用于指示其状态。" + }, + "permission": { + "permissionMode": { + "currentMode": "当前权限模式", + "backendMode": "后台权限模式", + "frontendMode": "前端角色权限模式", + "toggleMode": "切换权限模式" + }, + "pageTitles": { + "frontend": "前端权限示例", + "backend": "后端权限示例", + "button": "按钮权限控制" + }, + "roleButtonText": "拥有 { role } 角色权限可见", + "codeButtonText": "拥有code { code } 权限可见", + "currentPermissionMode": "当前权限模式", + "currentRole": "当前角色", + "currentCode": "当前code", + "clickToSeeButtonChange": "点击后请查看按钮变化", + "clickToSeeLeftMenuChange": "点击后请查看左侧菜单变化", + "frontendPermissionSwitchTitle": "权限切换(请先切换权限模式为前端角色权限模式)", + "backendPermissionSwitchTitle": "权限切换(请先切换权限模式为后端角色权限模式)", + "componentWayTitle": "组件方式判断权限(有需要可以自行全局注册)", + "functionWayTitle": "函数方式方式判断权限(适用于函数内部过滤)", + "functionWayButtonBoth": "拥有[USER,ADMIN]角色权限可见", + "directiveWayTitle": "指令方式方式判断权限(该方式不能动态修改权限.)", + "backendLeftMenuChangeTitle": "点击后请查看左侧菜单变化(必须处于后台权限模式才可测试此页面所展示的功能)" + }, + "headlessTable": { + "pageTitles": { + "basic": "基础表格" + } + }, + "result": { + "status": { + "error": "错误", + "success": "成功" + }, + "failPage": { + "title": "内容发送出错", + "subTitle": "很抱歉,发送内容时出现了问题。", + "buttons": { + "home": "返回主页", + "back": "返回上一级" + }, + "errorHeader": "发送内容出错时可能会有以下问题:", + "networkIssue": "网络连接问题", + "checkNetwork": "检查网络 >", + "messageTooLong": "消息过长,请精简一些", + "viewHelp": "查看帮助 >" + }, + "successPage": { + "title": "操作成功", + "subTitle": "ChatGPT 生成的内容已成功创建。", + "buttons": { + "home": "返回主页" + }, + "contentHeader": "AIGC 生成内容:", + "generatedTimeLabel": "生成时间", + "generatorLabel": "生成者", + "generatedContent": "在此显示生成的内容", + "contentLabel": "内容", + "step1": "输入内容", + "step2": "生成中", + "step2Content": "ChatGPT 正在生成内容,请稍等片刻。", + "step3": "审核中", + "step3Content": "生成的内容正在审核中,将很快完成审核。", + "step4": "完成" + } + } + } +} diff --git a/apps/thin/src/main.ts b/apps/thin/src/main.ts new file mode 100644 index 00000000..5a96dc4f --- /dev/null +++ b/apps/thin/src/main.ts @@ -0,0 +1,43 @@ +import { createApp } from "vue"; + +import { setupDirectives } from "@celeris/directives"; +import { setupI18n } from "@celeris/locale"; +import { router, setupRouter } from "./router"; +import { setupStore } from "./store"; +import { setupPermissionDirective } from "~/directives/permission"; +import { initializeConfiguration } from "~/AppConfiguration"; +import { setupRouterGuard } from "~/router/guard"; + +import App from "~/App.vue"; + +import "@celeris/styles"; + +const app = createApp(App); + +// Configure store +// 配置 store +setupStore(app); + +// Configure routing +// 配置路由 +setupRouter(app); + +// Configure router guard +// 配置路由守卫 +setupRouterGuard(router); + +// Register global directive +// 注册全局指令 +setupDirectives(app); +setupPermissionDirective(app); + +void Promise.all([ + // Initialize internal system configuration + // 初始化内部系统配置 + initializeConfiguration(), + // Configure i18n + // 配置国际化 + setupI18n(app), +]).finally(() => { + app.mount("#app"); +}); diff --git a/apps/thin/src/pages/dashboard/components/APIHealthMetrics.vue b/apps/thin/src/pages/dashboard/components/APIHealthMetrics.vue new file mode 100644 index 00000000..2b097e04 --- /dev/null +++ b/apps/thin/src/pages/dashboard/components/APIHealthMetrics.vue @@ -0,0 +1,29 @@ + + + + + diff --git a/apps/thin/src/pages/dashboard/components/CardInnerIcon.vue b/apps/thin/src/pages/dashboard/components/CardInnerIcon.vue new file mode 100644 index 00000000..7f08ef02 --- /dev/null +++ b/apps/thin/src/pages/dashboard/components/CardInnerIcon.vue @@ -0,0 +1,49 @@ + + + + + diff --git a/apps/thin/src/pages/dashboard/components/DataOverview.vue b/apps/thin/src/pages/dashboard/components/DataOverview.vue new file mode 100644 index 00000000..370da557 --- /dev/null +++ b/apps/thin/src/pages/dashboard/components/DataOverview.vue @@ -0,0 +1,272 @@ + + + + + diff --git a/apps/thin/src/pages/dashboard/components/PerformanceMetrics.vue b/apps/thin/src/pages/dashboard/components/PerformanceMetrics.vue new file mode 100644 index 00000000..556d2ef6 --- /dev/null +++ b/apps/thin/src/pages/dashboard/components/PerformanceMetrics.vue @@ -0,0 +1,105 @@ + + + + + diff --git a/apps/thin/src/pages/dashboard/components/PopularAssistants.vue b/apps/thin/src/pages/dashboard/components/PopularAssistants.vue new file mode 100644 index 00000000..5e8d0724 --- /dev/null +++ b/apps/thin/src/pages/dashboard/components/PopularAssistants.vue @@ -0,0 +1,15 @@ + + + + + diff --git a/apps/thin/src/pages/dashboard/components/ResponseTypeDistribution.vue b/apps/thin/src/pages/dashboard/components/ResponseTypeDistribution.vue new file mode 100644 index 00000000..e76444d4 --- /dev/null +++ b/apps/thin/src/pages/dashboard/components/ResponseTypeDistribution.vue @@ -0,0 +1,15 @@ + + + + + diff --git a/apps/thin/src/pages/dashboard/components/UserAnalysis.vue b/apps/thin/src/pages/dashboard/components/UserAnalysis.vue new file mode 100644 index 00000000..255989ab --- /dev/null +++ b/apps/thin/src/pages/dashboard/components/UserAnalysis.vue @@ -0,0 +1,24 @@ + + + + + diff --git a/apps/thin/src/pages/dashboard/components/UserAnalysisItem.vue b/apps/thin/src/pages/dashboard/components/UserAnalysisItem.vue new file mode 100644 index 00000000..9bc86578 --- /dev/null +++ b/apps/thin/src/pages/dashboard/components/UserAnalysisItem.vue @@ -0,0 +1,127 @@ + + + + + diff --git a/apps/thin/src/pages/dashboard/index.vue b/apps/thin/src/pages/dashboard/index.vue new file mode 100644 index 00000000..a59a75cf --- /dev/null +++ b/apps/thin/src/pages/dashboard/index.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/apps/thin/src/pages/internal/exception/Exception.vue b/apps/thin/src/pages/internal/exception/Exception.vue new file mode 100644 index 00000000..ec042728 --- /dev/null +++ b/apps/thin/src/pages/internal/exception/Exception.vue @@ -0,0 +1,65 @@ + + + diff --git a/apps/thin/src/pages/internal/iframe/IframeContainer.vue b/apps/thin/src/pages/internal/iframe/IframeContainer.vue new file mode 100644 index 00000000..1b7f4319 --- /dev/null +++ b/apps/thin/src/pages/internal/iframe/IframeContainer.vue @@ -0,0 +1,32 @@ + + + diff --git a/apps/thin/src/pages/internal/iframe/IframePage.vue b/apps/thin/src/pages/internal/iframe/IframePage.vue new file mode 100644 index 00000000..f41e76b4 --- /dev/null +++ b/apps/thin/src/pages/internal/iframe/IframePage.vue @@ -0,0 +1,32 @@ + + +