diff --git a/apps/antd-view/src/apis/index.ts b/apps/antd-view/src/apis/index.ts new file mode 100644 index 00000000..26086dcf --- /dev/null +++ b/apps/antd-view/src/apis/index.ts @@ -0,0 +1,2 @@ +export * from './modules'; +export type * from './types'; diff --git a/apps/antd-view/src/apis/modules/index.ts b/apps/antd-view/src/apis/modules/index.ts new file mode 100644 index 00000000..e5abc856 --- /dev/null +++ b/apps/antd-view/src/apis/modules/index.ts @@ -0,0 +1 @@ +export * from './user'; diff --git a/apps/antd-view/src/apis/modules/user.ts b/apps/antd-view/src/apis/modules/user.ts new file mode 100644 index 00000000..b24a720a --- /dev/null +++ b/apps/antd-view/src/apis/modules/user.ts @@ -0,0 +1,22 @@ +import type { UserApiType } from '@/apis/types'; +import type { UserInfo } from '@vben/types'; + +import { request } from '@/apis/request'; + +/** + * 登录 + */ +async function userLogin(data: UserApiType.LoginParams) { + return request('/login', { data, method: 'post' }); +} + +/** + * 获取用户信息 + */ +async function getUserInfo() { + return request('/getUserInfo', { method: 'get' }); +} + +export { getUserInfo, userLogin }; + +export * from './user'; diff --git a/apps/antd-view/src/services/request.ts b/apps/antd-view/src/apis/request.ts similarity index 100% rename from apps/antd-view/src/services/request.ts rename to apps/antd-view/src/apis/request.ts diff --git a/apps/antd-view/src/apis/types/index.ts b/apps/antd-view/src/apis/types/index.ts new file mode 100644 index 00000000..d20c6861 --- /dev/null +++ b/apps/antd-view/src/apis/types/index.ts @@ -0,0 +1 @@ +export type * from './user'; diff --git a/apps/antd-view/src/services/modules/user/typing.ts b/apps/antd-view/src/apis/types/user.ts similarity index 84% rename from apps/antd-view/src/services/modules/user/typing.ts rename to apps/antd-view/src/apis/types/user.ts index 50dbf458..2c23ea24 100644 --- a/apps/antd-view/src/services/modules/user/typing.ts +++ b/apps/antd-view/src/apis/types/user.ts @@ -1,4 +1,4 @@ -namespace UserApi { +namespace UserApiType { /** 登录接口参数 */ export interface LoginParams { password: string; @@ -15,4 +15,4 @@ namespace UserApi { } } -export type { UserApi }; +export type { UserApiType }; diff --git a/apps/antd-view/src/services/index.ts b/apps/antd-view/src/services/index.ts deleted file mode 100644 index 9f13af01..00000000 --- a/apps/antd-view/src/services/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './modules/user'; diff --git a/apps/antd-view/src/services/modules/user/index.ts b/apps/antd-view/src/services/modules/user/index.ts deleted file mode 100644 index 4fcf798e..00000000 --- a/apps/antd-view/src/services/modules/user/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { UserInfo } from '@vben/types'; - -import { request } from '@/services/request'; - -import type { UserApi } from './typing'; - -/** - * 登录 - */ -async function userLogin(data: UserApi.LoginParams) { - return request('/login', { data, method: 'post' }); -} - -/** - * 获取用户信息 - */ -async function getUserInfo() { - return request('/getUserInfo', { method: 'get' }); -} - -export { getUserInfo, userLogin }; - -export type { UserApi } from './typing'; diff --git a/apps/antd-view/src/views/_essential/authentication/login.vue b/apps/antd-view/src/views/_essential/authentication/login.vue index 18ef3f8f..a0468276 100644 --- a/apps/antd-view/src/views/_essential/authentication/login.vue +++ b/apps/antd-view/src/views/_essential/authentication/login.vue @@ -3,7 +3,7 @@ import type { LoginAndRegisterParams } from '@vben/common-ui'; import { useAccessStore } from '@vben-core/stores'; -import { getUserInfo, userLogin } from '@/services'; +import { getUserInfo, userLogin } from '@/apis'; import { AuthenticationLogin } from '@vben/common-ui'; import { $t } from '@vben/locales'; import { useRequest } from '@vben/request'; diff --git a/internal/tailwind-config/package.json b/internal/tailwind-config/package.json index e9b951e8..ae0f9c4b 100644 --- a/internal/tailwind-config/package.json +++ b/internal/tailwind-config/package.json @@ -44,6 +44,9 @@ }, "./*": "./*" }, + "peerDependencies": { + "tailwindcss": "^3.4.3" + }, "dependencies": { "@iconify/json": "^2.2.215", "@iconify/tailwind": "^1.1.1", diff --git a/internal/tailwind-config/src/index.ts b/internal/tailwind-config/src/index.ts index ff46fc2a..0c2e85dd 100644 --- a/internal/tailwind-config/src/index.ts +++ b/internal/tailwind-config/src/index.ts @@ -8,6 +8,8 @@ import typographyPlugin from '@tailwindcss/typography'; import { fs, getPackagesSync } from '@vben/node-utils'; import animate from 'tailwindcss-animate'; +import { enterAnimationPlugin } from './plugins/entry'; + // import defaultTheme from 'tailwindcss/defaultTheme'; const { packages } = getPackagesSync(); @@ -29,7 +31,13 @@ export default { ), ], darkMode: 'class', - plugins: [animate, formsPlugin, typographyPlugin, addDynamicIconSelectors()], + plugins: [ + animate, + formsPlugin, + typographyPlugin, + addDynamicIconSelectors(), + enterAnimationPlugin, + ], prefix: '', safelist: ['dark'], theme: { diff --git a/internal/tailwind-config/src/plugins/entry.ts b/internal/tailwind-config/src/plugins/entry.ts new file mode 100644 index 00000000..0d8e8ec8 --- /dev/null +++ b/internal/tailwind-config/src/plugins/entry.ts @@ -0,0 +1,53 @@ +import plugin from 'tailwindcss/plugin.js'; + +const enterAnimationPlugin = plugin(({ addUtilities }) => { + const maxChild = 5; + const utilities: Record = {}; + for (let i = 1; i <= maxChild; i++) { + const baseDelay = 0.1; + const delay = `${baseDelay * i}s`; + + utilities[`.enter-x:nth-child(${i})`] = { + animation: `enter-x-animation 0.3s ease-in-out ${delay} forwards`, + opacity: '0', + transform: `translateX(50px)`, + }; + + utilities[`.enter-y:nth-child(${i})`] = { + animation: `enter-y-animation 0.3s ease-in-out ${delay} forwards`, + opacity: '0', + transform: `translateY(50px)`, + }; + + utilities[`.-enter-x:nth-child(${i})`] = { + animation: `enter-x-animation 0.3s ease-in-out ${delay} forwards`, + opacity: '0', + transform: `translateX(-50px)`, + }; + + utilities[`.-enter-y:nth-child(${i})`] = { + animation: `enter-y-animation 0.3s ease-in-out ${delay} forwards`, + opacity: '0', + transform: `translateY(-50px)`, + }; + } + + // 添加动画关键帧 + addUtilities(utilities); + addUtilities({ + '@keyframes enter-x-animation': { + to: { + opacity: '1', + transform: 'translateX(0)', + }, + }, + '@keyframes enter-y-animation': { + to: { + opacity: '1', + transform: 'translateY(0)', + }, + }, + }); +}); + +export { enterAnimationPlugin }; diff --git a/packages/@vben-core/forward/preferences/src/constants.ts b/packages/@vben-core/forward/preferences/src/constants.ts index 5e4b679b..116cb2d2 100644 --- a/packages/@vben-core/forward/preferences/src/constants.ts +++ b/packages/@vben-core/forward/preferences/src/constants.ts @@ -1,7 +1,7 @@ -import type { LocaleSupportType } from './types'; +import type { SupportedLanguagesType } from './types'; interface Language { - key: LocaleSupportType; + key: SupportedLanguagesType; text: string; } diff --git a/packages/@vben-core/forward/preferences/src/preferences.ts b/packages/@vben-core/forward/preferences/src/preferences.ts index 4d3067ba..aa247adf 100644 --- a/packages/@vben-core/forward/preferences/src/preferences.ts +++ b/packages/@vben-core/forward/preferences/src/preferences.ts @@ -96,7 +96,7 @@ class PreferenceManager { * 加载偏好设置 * @returns {Preferences} 加载的偏好设置 */ - private loadPreferences(): Preferences | null { + private loadPreferences(): Preferences { return this.loadCachedPreferences() || { ...defaultPreferences }; } diff --git a/packages/@vben-core/forward/preferences/src/types.ts b/packages/@vben-core/forward/preferences/src/types.ts index 81930555..17e016a1 100644 --- a/packages/@vben-core/forward/preferences/src/types.ts +++ b/packages/@vben-core/forward/preferences/src/types.ts @@ -2,7 +2,7 @@ import type { ContentCompactType, LayoutHeaderModeType, LayoutType, - LocaleSupportType, + SupportedLanguagesType, ThemeModeType, } from '@vben-core/typings'; @@ -36,7 +36,7 @@ interface AppPreferences { /** 布局方式 */ layout: LayoutType; /** 支持的语言 */ - locale: LocaleSupportType; + locale: SupportedLanguagesType; /** 应用名 */ name: string; /** 是否开启半深色菜单(只在theme='light'时生效) */ @@ -174,7 +174,6 @@ export type { HeaderPreferences, LayoutHeaderModeType, LayoutType, - LocaleSupportType, LogoPreferences, NavigationPreferences, PageTransitionType, @@ -182,6 +181,7 @@ export type { PreferencesKeys, ShortcutKeyPreferences, SidebarPreferences, + SupportedLanguagesType, TabbarPreferences, ThemeModeType, ThemePreferences, diff --git a/packages/@vben-core/forward/stores/src/modules/access.ts b/packages/@vben-core/forward/stores/src/modules/access.ts index 1cb985a5..34fe3571 100644 --- a/packages/@vben-core/forward/stores/src/modules/access.ts +++ b/packages/@vben-core/forward/stores/src/modules/access.ts @@ -1,4 +1,4 @@ -import type { MenuRecordRaw, UserInfo } from '@vben-core/typings'; +import type { MenuRecordRaw } from '@vben-core/typings'; import type { RouteRecordRaw } from 'vue-router'; @@ -6,6 +6,28 @@ import { acceptHMRUpdate, defineStore } from 'pinia'; type AccessToken = null | string; +interface BasicUserInfo { + [key: string]: any; + /** + * 头像 + */ + avatar: string; + /** + * 用户昵称 + */ + realName: string; + + /** + * 用户id + */ + userId: string; + + /** + * 用户名 + */ + username: string; +} + interface AccessState { /** * 可访问的菜单列表 @@ -22,7 +44,7 @@ interface AccessState { /** * 用户信息 */ - userInfo: UserInfo | null; + userInfo: BasicUserInfo | null; /** * 用户角色 */ @@ -43,12 +65,15 @@ const useAccessStore = defineStore('access', { setAccessToken(token: AccessToken) { this.accessToken = token; }, - setUserInfo(userInfo: UserInfo) { + setUserInfo(userInfo: BasicUserInfo) { // 设置用户信息 this.userInfo = userInfo; // 设置角色信息 const roles = userInfo?.roles ?? []; - const roleValues = roles.map((item) => item.value); + const roleValues = + typeof roles[0] === 'string' + ? roles + : roles.map((item: Record) => item.value); this.setUserRoles(roleValues); }, setUserRoles(roles: string[]) { @@ -65,7 +90,7 @@ const useAccessStore = defineStore('access', { getAccessToken(): AccessToken { return this.accessToken; }, - getUserInfo(): UserInfo | null { + getUserInfo(): BasicUserInfo | null { return this.userInfo; }, getUserRoles(): string[] { diff --git a/packages/@vben-core/shared/design/src/index.css b/packages/@vben-core/shared/design/src/index.css new file mode 100644 index 00000000..931c8ecc --- /dev/null +++ b/packages/@vben-core/shared/design/src/index.css @@ -0,0 +1,327 @@ +@charset "UTF-8"; + +/** css 样式重置 */ +@import 'modern-normalize/modern-normalize.css'; + +#app, +.ant-app, +body, +html { + width: 100%; + height: 100%; + overscroll-behavior: none; +} + +*, +::after, +::before { + @apply border-border; + + box-sizing: border-box; + border-style: solid; + border-width: 0; +} + +body.invert-mode { + @apply invert; +} + +body.grayscale-mode { + @apply grayscale; +} + +html { + @apply text-foreground bg-background; + + font-variation-settings: normal; + text-size-adjust: 100%; + font-synthesis-weight: none; + scroll-behavior: smooth; + text-rendering: optimizelegibility; + -webkit-tap-highlight-color: transparent; +} + +a, +a:active, +a:hover, +a:link, +a:visited { + color: inherit; + text-decoration: none; +} + +::view-transition-new(root), +::view-transition-old(root) { + mix-blend-mode: normal; + animation: none; +} + +::view-transition-old(root) { + z-index: 1; +} + +::view-transition-new(root) { + z-index: 2147483646; +} + +html.dark::view-transition-old(root) { + z-index: 2147483646; +} + +html.dark::view-transition-new(root) { + z-index: 1; +} + +input::placeholder, +textarea::placeholder { + opacity: 1; +} + +input:-webkit-autofill { + border: none; + box-shadow: 0 0 0 1000px transparent inset; +} + +input[type='number']::-webkit-inner-spin-button, +input[type='number']::-webkit-outer-spin-button { + margin: 0; + appearance: none; +} + +.slide-up-enter-active, +.slide-up-leave-active { + transition: 0.25s cubic-bezier(0.25, 0.8, 0.5, 1); +} + +.slide-up-move { + transition: transform 0.3s; +} + +.slide-up-enter-from, +.slide-up-leave-to { + opacity: 0; + transform: translateY(-15px); +} + +.slide-down-enter-active, +.slide-down-leave-active { + transition: 0.25s cubic-bezier(0.25, 0.8, 0.5, 1); +} + +.slide-down-move { + transition: transform 0.3s; +} + +.slide-down-enter-from, +.slide-down-leave-to { + opacity: 0; + transform: translateY(15px); +} + +.slide-left-enter-active, +.slide-left-leave-active { + transition: 0.25s cubic-bezier(0.25, 0.8, 0.5, 1); +} + +.slide-left-move { + transition: transform 0.3s; +} + +.slide-left-enter-from, +.slide-left-leave-to { + opacity: 0; + transform: translateX(-15px); +} + +.slide-right-enter-active, +.slide-right-leave-active { + transition: 0.25s cubic-bezier(0.25, 0.8, 0.5, 1); +} + +.slide-right-move { + transition: transform 0.3s; +} + +.slide-right-enter-from, +.slide-right-leave-to { + opacity: 0; + transform: translateX(15px); +} + +.fade-transition-enter-active, +.fade-transition-leave-active { + transition: opacity 0.2s ease-in-out; +} + +.fade-transition-enter-from, +.fade-transition-leave-to { + opacity: 0; +} + +.fade-enter-active, +.fade-leave-active { + transition: opacity 0.2s ease-in-out; +} + +.fade-enter-from, +.fade-leave-to { + opacity: 0; +} + +/* fade-slide */ +.fade-slide-leave-active, +.fade-slide-enter-active { + transition: all 0.3s; +} + +.fade-slide-enter-from { + opacity: 0; + transform: translateX(-30px); +} + +.fade-slide-leave-to { + opacity: 0; + transform: translateX(30px); +} + +.fade-down-enter-active, +.fade-down-leave-active { + transition: + opacity 0.25s, + transform 0.3s; +} + +.fade-down-enter-from { + opacity: 0; + transform: translateY(-10%); +} + +.fade-down-leave-to { + opacity: 0; + transform: translateY(10%); +} + +.fade-scale-leave-active, +.fade-scale-enter-active { + transition: all 0.28s; +} + +.fade-scale-enter-from { + opacity: 0; + transform: scale(1.2); +} + +.fade-scale-leave-to { + opacity: 0; + transform: scale(0.8); +} + +.fade-up-enter-active, +.fade-up-leave-active { + transition: + opacity 0.2s, + transform 0.25s; +} + +.fade-up-enter-from { + opacity: 0; + transform: translateY(10%); +} + +.fade-up-leave-to { + opacity: 0; + transform: translateY(-10%); +} + +@keyframes fade-slide { + 0% { + opacity: 0; + transform: translateX(-30px); + } + + 50% { + opacity: 1; + } + + 100% { + opacity: 0; + transform: translateX(30px); + } +} + +@keyframes fade { + 0% { + opacity: 0; + } + + 50% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} + +@keyframes fade-up { + 0% { + opacity: 0; + transform: translateY(10%); + } + + 50% { + opacity: 1; + } + + 100% { + opacity: 0; + transform: translateY(-10%); + } +} + +@keyframes fade-down { + 0% { + opacity: 0; + transform: translateY(-10%); + } + + 50% { + opacity: 1; + } + + 100% { + opacity: 0; + transform: translateY(10%); + } +} + +.fade-slow { + animation: fade 3s infinite; +} + +.fade-slide-slow { + animation: fade-slide 3s infinite; +} + +.fade-up-slow { + animation: fade-up 3s infinite; +} + +.fade-down-slow { + animation: fade-down 3s infinite; +} + +.collapse-transition { + transition: + 0.2s height ease-in-out, + 0.2s padding-top ease-in-out, + 0.2s padding-bottom ease-in-out; +} + +.collapse-transition-leave-active, +.collapse-transition-enter-active { + transition: + 0.2s max-height ease-in-out, + 0.2s padding-top ease-in-out, + 0.2s margin-top ease-in-out; +} diff --git a/packages/@vben-core/shared/design/src/tailwind.css b/packages/@vben-core/shared/design/src/tailwind.css index 0016ccab..5bd546f0 100644 --- a/packages/@vben-core/shared/design/src/tailwind.css +++ b/packages/@vben-core/shared/design/src/tailwind.css @@ -19,21 +19,21 @@ .outline-box { @apply outline-border relative cursor-pointer rounded-md p-1 outline outline-1; + } - &::after { - @apply absolute left-1/2 top-1/2 z-20 h-0 w-[1px] rounded-sm opacity-0 outline outline-2 outline-transparent transition-all duration-300 content-['']; - } + .outline-box::after { + @apply absolute left-1/2 top-1/2 z-20 h-0 w-[1px] rounded-sm opacity-0 outline outline-2 outline-transparent transition-all duration-300 content-[""]; + } - &.outline-box-active { - @apply outline-primary outline outline-2; + .outline-box.outline-box-active { + @apply outline-primary outline outline-2; + } - &::after { - display: none; - } - } + .outline-box.outline-box-active::after { + display: none; + } - &:not(.outline-box-active):hover::after { - @apply outline-primary left-0 top-0 h-full w-full p-1 opacity-100; - } + .outline-box:not(.outline-box-active):hover::after { + @apply outline-primary left-0 top-0 h-full w-full p-1 opacity-100; } } diff --git a/packages/@vben-core/shared/typings/src/app.ts b/packages/@vben-core/shared/typings/src/app.d.ts similarity index 83% rename from packages/@vben-core/shared/typings/src/app.ts rename to packages/@vben-core/shared/typings/src/app.d.ts index 0f94746c..ec6155dd 100644 --- a/packages/@vben-core/shared/typings/src/app.ts +++ b/packages/@vben-core/shared/typings/src/app.d.ts @@ -1,4 +1,4 @@ -type LocaleSupportType = 'en-US' | 'zh-CN'; +type SupportedLanguagesType = 'en-US' | 'zh-CN'; type LayoutType = | 'full-content' @@ -17,6 +17,6 @@ export type { ContentCompactType, LayoutHeaderModeType, LayoutType, - LocaleSupportType, + SupportedLanguagesType, ThemeModeType, }; diff --git a/packages/@vben-core/shared/typings/src/tools.ts b/packages/@vben-core/shared/typings/src/helper.d.ts similarity index 100% rename from packages/@vben-core/shared/typings/src/tools.ts rename to packages/@vben-core/shared/typings/src/helper.d.ts diff --git a/packages/@vben-core/shared/typings/src/index.ts b/packages/@vben-core/shared/typings/src/index.ts index 25beb352..e8f8d09f 100644 --- a/packages/@vben-core/shared/typings/src/index.ts +++ b/packages/@vben-core/shared/typings/src/index.ts @@ -1,7 +1,6 @@ -export type * from './access'; export type * from './app'; export type * from './flatten'; +export type * from './helper'; export type * from './menu-record'; export type * from './tabs'; -export type * from './tools'; export type * from './vue-router'; diff --git a/packages/@vben-core/shared/typings/src/vue-router.ts b/packages/@vben-core/shared/typings/src/vue-router.d.ts similarity index 100% rename from packages/@vben-core/shared/typings/src/vue-router.ts rename to packages/@vben-core/shared/typings/src/vue-router.d.ts diff --git a/packages/business/common-ui/src/language-toggle/language-toggle.vue b/packages/business/common-ui/src/language-toggle/language-toggle.vue index a187759e..0666ca4d 100644 --- a/packages/business/common-ui/src/language-toggle/language-toggle.vue +++ b/packages/business/common-ui/src/language-toggle/language-toggle.vue @@ -1,5 +1,5 @@