From 6b1cf17428163207827281aa8e9516d453c7c51b Mon Sep 17 00:00:00 2001 From: xlsea Date: Thu, 21 Mar 2024 11:53:27 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AF=B9=E6=8E=A5=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E5=92=8C=E5=91=BD=E5=90=8D=E7=A9=BA=E9=97=B4=E8=A7=84=E8=8C=83?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.test | 2 +- build/config/proxy.ts | 1 + package.json | 1 + pnpm-lock.yaml | 8 ++++ .../global-header/components/user-avatar.vue | 2 +- src/layouts/modules/global-header/index.vue | 2 + .../modules/namespace-select/index.vue | 37 +++++++++++++++++++ src/router/guard/permission.ts | 5 +-- src/service/api/auth.ts | 8 ++-- src/service/request/index.ts | 15 ++++---- src/store/modules/auth/index.ts | 4 +- src/store/modules/auth/shared.ts | 10 +++-- src/store/modules/route/index.ts | 6 +-- src/typings/api.d.ts | 20 ++++++++-- src/typings/app.d.ts | 4 +- src/typings/components.d.ts | 16 -------- src/typings/storage.d.ts | 2 + .../_builtin/login/modules/pwd-login.vue | 10 +++-- src/views/home/modules/header-banner.vue | 2 +- 19 files changed, 104 insertions(+), 51 deletions(-) create mode 100644 src/layouts/modules/namespace-select/index.vue diff --git a/.env.test b/.env.test index 0f3c35c..6133374 100644 --- a/.env.test +++ b/.env.test @@ -1,5 +1,5 @@ # backend service base url, test environment -VITE_SERVICE_BASE_URL=https://mock.apifox.com/m1/3109515-0-default +VITE_SERVICE_BASE_URL=http://preview.easyretry.com/easy-retry # other backend service base url, test environment VITE_OTHER_SERVICE_BASE_URL= `{ diff --git a/build/config/proxy.ts b/build/config/proxy.ts index 350dfee..e140095 100644 --- a/build/config/proxy.ts +++ b/build/config/proxy.ts @@ -29,6 +29,7 @@ function createProxyItem(item: App.Service.ServiceConfigItem) { proxy[item.proxyPattern] = { target: item.baseURL, changeOrigin: true, + ws: false, rewrite: path => path.replace(new RegExp(`^${item.proxyPattern}`), '') }; diff --git a/package.json b/package.json index 91d03aa..9af16db 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "naive-ui": "2.38.1", "nprogress": "0.2.0", "pinia": "2.1.7", + "ts-md5": "^1.3.1", "vue": "3.4.21", "vue-draggable-plus": "0.3.5", "vue-i18n": "9.10.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5120c16..f0c0a80 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -53,6 +53,9 @@ importers: pinia: specifier: 2.1.7 version: 2.1.7(typescript@5.4.2)(vue@3.4.21) + ts-md5: + specifier: ^1.3.1 + version: 1.3.1 vue: specifier: 3.4.21 version: 3.4.21(typescript@5.4.2) @@ -7330,6 +7333,11 @@ packages: typescript: 5.4.2 dev: true + /ts-md5@1.3.1: + resolution: {integrity: sha512-DiwiXfwvcTeZ5wCE0z+2A9EseZsztaiZtGrtSaY5JOD7ekPnR/GoIVD5gXZAlK9Na9Kvpo9Waz5rW64WKAWApg==} + engines: {node: '>=12'} + dev: false + /tslib@2.3.0: resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==} dev: false diff --git a/src/layouts/modules/global-header/components/user-avatar.vue b/src/layouts/modules/global-header/components/user-avatar.vue index e2de0ed..be42a68 100644 --- a/src/layouts/modules/global-header/components/user-avatar.vue +++ b/src/layouts/modules/global-header/components/user-avatar.vue @@ -82,7 +82,7 @@ function handleDropdown(key: DropdownKey) {
- {{ authStore.userInfo.userName }} + {{ authStore.userInfo.username }}
diff --git a/src/layouts/modules/global-header/index.vue b/src/layouts/modules/global-header/index.vue index ae372c4..aba546a 100644 --- a/src/layouts/modules/global-header/index.vue +++ b/src/layouts/modules/global-header/index.vue @@ -8,6 +8,7 @@ import HorizontalMenu from '../global-menu/base-menu.vue'; import GlobalLogo from '../global-logo/index.vue'; import GlobalBreadcrumb from '../global-breadcrumb/index.vue'; import GlobalSearch from '../global-search/index.vue'; +import NamespaceSelect from '../namespace-select/index.vue'; import { useMixMenuContext } from '../../hooks/use-mix-menu'; import ThemeButton from './components/theme-button.vue'; import UserAvatar from './components/user-avatar.vue'; @@ -55,6 +56,7 @@ const headerMenus = computed(() => {
+ diff --git a/src/layouts/modules/namespace-select/index.vue b/src/layouts/modules/namespace-select/index.vue new file mode 100644 index 0000000..51dd3ee --- /dev/null +++ b/src/layouts/modules/namespace-select/index.vue @@ -0,0 +1,37 @@ + + + + + diff --git a/src/router/guard/permission.ts b/src/router/guard/permission.ts index 9e047f9..e1da8ae 100644 --- a/src/router/guard/permission.ts +++ b/src/router/guard/permission.ts @@ -30,10 +30,7 @@ export function createPermissionGuard(router: Router) { // 2. if the user is super admin, then it is allowed to access // 3. if the user's role is included in the route's "roles", then it is allowed to access const SUPER_ADMIN = 'R_SUPER'; - const hasPermission = - !routeRoles.length || - authStore.userInfo.roles.includes(SUPER_ADMIN) || - authStore.userInfo.roles.some(role => routeRoles.includes(role)); + const hasPermission = !routeRoles.length || authStore.userInfo.role === SUPER_ADMIN; const strategicPatterns: CommonType.StrategicPattern[] = [ // 1. if it is login route when logged in, change to the root page diff --git a/src/service/api/auth.ts b/src/service/api/auth.ts index 5e57fb4..31496dc 100644 --- a/src/service/api/auth.ts +++ b/src/service/api/auth.ts @@ -3,15 +3,15 @@ import { request } from '../request'; /** * Login * - * @param userName User name + * @param username User name * @param password Password */ -export function fetchLogin(userName: string, password: string) { +export function fetchLogin(username: string, password: string) { return request({ url: '/auth/login', method: 'post', data: { - userName, + username, password } }); @@ -19,7 +19,7 @@ export function fetchLogin(userName: string, password: string) { /** Get user info */ export function fetchGetUserInfo() { - return request({ url: '/auth/getUserInfo' }); + return request({ url: '/user/info' }); } /** diff --git a/src/service/request/index.ts b/src/service/request/index.ts index f4b384a..c8d45c9 100644 --- a/src/service/request/index.ts +++ b/src/service/request/index.ts @@ -8,9 +8,7 @@ const { baseURL, otherBaseURL } = getServiceBaseURL(import.meta.env, isHttpProxy export const request = createFlatRequest( { baseURL, - headers: { - apifoxToken: 'XL299LiMEDZ0H5h3A29PxwQXdMJqWyY2' - } + timeout: 6000 }, { async onRequest(config) { @@ -18,15 +16,18 @@ export const request = createFlatRequest( // set token const token = localStg.get('token'); - const Authorization = token ? `Bearer ${token}` : null; - Object.assign(headers, { Authorization }); + const namespaceId = localStg.get('namespaceId'); + // const Authorization = token ? `Bearer ${token}` : null; + headers['EASY-RETRY-AUTH'] = token; + headers['EASY-RETRY-NAMESPACE-ID'] = namespaceId; + Object.assign(headers, { 'EASY-RETRY-AUTH': token, 'EASY-RETRY-NAMESPACE-ID': namespaceId }); return config; }, isBackendSuccess(response) { // when the backend response code is "0000", it means the request is success // you can change this logic by yourself - return response.data.code === '0000'; + return response.data.status === 1; }, async onBackendFail(_response) { // when the backend response code is not "0000", it means the request is fail @@ -42,7 +43,7 @@ export const request = createFlatRequest( // show backend error message if (error.code === BACKEND_ERROR_CODE) { - message = error.response?.data?.msg || message; + message = error.response?.data?.message || message; } window.$message?.error(message); diff --git a/src/store/modules/auth/index.ts b/src/store/modules/auth/index.ts index 96508e3..8008944 100644 --- a/src/store/modules/auth/index.ts +++ b/src/store/modules/auth/index.ts @@ -58,7 +58,7 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => { if (routeStore.isInitAuthRoute) { window.$notification?.success({ title: $t('page.login.common.loginSuccess'), - content: $t('page.login.common.welcomeBack', { userName: userInfo.userName }), + content: $t('page.login.common.welcomeBack', { userName: userInfo.username }), duration: 4500 }); } @@ -73,7 +73,7 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => { async function loginByToken(loginToken: Api.Auth.LoginToken) { // 1. stored in the localStorage, the later requests need it in headers localStg.set('token', loginToken.token); - localStg.set('refreshToken', loginToken.refreshToken); + localStg.set('namespaceId', loginToken.namespaceIds[0].uniqueId); const { data: info, error } = await fetchGetUserInfo(); diff --git a/src/store/modules/auth/shared.ts b/src/store/modules/auth/shared.ts index 5a6bf42..b7138c0 100644 --- a/src/store/modules/auth/shared.ts +++ b/src/store/modules/auth/shared.ts @@ -8,9 +8,11 @@ export function getToken() { /** Get user info */ export function getUserInfo() { const emptyInfo: Api.Auth.UserInfo = { - userId: '', - userName: '', - roles: [] + id: '', + mode: '', + username: '', + role: '', + namespaceIds: [] }; const userInfo = localStg.get('userInfo') || emptyInfo; @@ -20,6 +22,6 @@ export function getUserInfo() { /** Clear auth storage */ export function clearAuthStorage() { localStg.remove('token'); - localStg.remove('refreshToken'); + localStg.remove('namespaceId'); localStg.remove('userInfo'); } diff --git a/src/store/modules/route/index.ts b/src/store/modules/route/index.ts index c3937e7..15fb5ad 100644 --- a/src/store/modules/route/index.ts +++ b/src/store/modules/route/index.ts @@ -9,7 +9,7 @@ import { ROOT_ROUTE, createRoutes, getAuthVueRoutes } from '@/router/routes'; import { getRouteName, getRoutePath } from '@/router/elegant/transform'; import { fetchGetUserRoutes, fetchIsRouteExist } from '@/service/api'; import { useAppStore } from '../app'; -import { useAuthStore } from '../auth'; +// import { useAuthStore } from '../auth'; import { useTabStore } from '../tab'; import { filterAuthRoutesByRoles, @@ -25,7 +25,7 @@ import { export const useRouteStore = defineStore(SetupStoreId.Route, () => { const appStore = useAppStore(); - const authStore = useAuthStore(); + // const authStore = useAuthStore(); const tabStore = useTabStore(); const { bool: isInitAuthRoute, setBool: setIsInitAuthRoute } = useBoolean(); const removeRouteFns: (() => void)[] = []; @@ -160,7 +160,7 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => { async function initStaticAuthRoute() { const { authRoutes } = createRoutes(); - const filteredAuthRoutes = filterAuthRoutesByRoles(authRoutes, authStore.userInfo.roles); + const filteredAuthRoutes = filterAuthRoutesByRoles(authRoutes, []); handleAuthRoutes(filteredAuthRoutes); diff --git a/src/typings/api.d.ts b/src/typings/api.d.ts index 03a70e7..afe0d3e 100644 --- a/src/typings/api.d.ts +++ b/src/typings/api.d.ts @@ -52,14 +52,28 @@ declare namespace Api { */ namespace Auth { interface LoginToken { + id: string; + mode: string; + role: String; token: string; refreshToken: string; + createDt: string; + updateDt: string; + namespaceIds: NamespaceId[]; } interface UserInfo { - userId: string; - userName: string; - roles: string[]; + id: string; + mode: string; + username: string; + role: string; + namespaceIds: NamespaceId[]; + } + + interface NamespaceId { + id: string; + name: string; + uniqueId: string; } } diff --git a/src/typings/app.d.ts b/src/typings/app.d.ts index 6dcf1ce..55f1f12 100644 --- a/src/typings/app.d.ts +++ b/src/typings/app.d.ts @@ -631,9 +631,9 @@ declare namespace App { /** The backend service response data */ type Response = { /** The backend service response code */ - code: string; + status: number; /** The backend service response message */ - msg: string; + message: string; /** The backend service response data */ data: T; }; diff --git a/src/typings/components.d.ts b/src/typings/components.d.ts index afeb02d..1917d6e 100644 --- a/src/typings/components.d.ts +++ b/src/typings/components.d.ts @@ -16,21 +16,14 @@ declare module 'vue' { FullScreen: typeof import('./../components/common/full-screen.vue')['default'] IconAntDesignEnterOutlined: typeof import('~icons/ant-design/enter-outlined')['default'] IconAntDesignReloadOutlined: typeof import('~icons/ant-design/reload-outlined')['default'] - IconAntDesignSettingOutlined: typeof import('~icons/ant-design/setting-outlined')['default'] IconGridiconsFullscreen: typeof import('~icons/gridicons/fullscreen')['default'] IconGridiconsFullscreenExit: typeof import('~icons/gridicons/fullscreen-exit')['default'] - IconIcRoundDelete: typeof import('~icons/ic/round-delete')['default'] - IconIcRoundPlus: typeof import('~icons/ic/round-plus')['default'] - IconIcRoundRefresh: typeof import('~icons/ic/round-refresh')['default'] - IconIcRoundSearch: typeof import('~icons/ic/round-search')['default'] IconLocalBanner: typeof import('~icons/local/banner')['default'] IconLocalLogo: typeof import('~icons/local/logo')['default'] IconMdiArrowDownThin: typeof import('~icons/mdi/arrow-down-thin')['default'] IconMdiArrowUpThin: typeof import('~icons/mdi/arrow-up-thin')['default'] - IconMdiDrag: typeof import('~icons/mdi/drag')['default'] IconMdiKeyboardEsc: typeof import('~icons/mdi/keyboard-esc')['default'] IconMdiKeyboardReturn: typeof import('~icons/mdi/keyboard-return')['default'] - IconMdiRefresh: typeof import('~icons/mdi/refresh')['default'] IconUilSearch: typeof import('~icons/uil/search')['default'] LangSwitch: typeof import('./../components/common/lang-switch.vue')['default'] LookForward: typeof import('./../components/custom/look-forward.vue')['default'] @@ -41,9 +34,6 @@ declare module 'vue' { NCard: typeof import('naive-ui')['NCard'] NCheckbox: typeof import('naive-ui')['NCheckbox'] NColorPicker: typeof import('naive-ui')['NColorPicker'] - NDataTable: typeof import('naive-ui')['NDataTable'] - NDescriptions: typeof import('naive-ui')['NDescriptions'] - NDescriptionsItem: typeof import('naive-ui')['NDescriptionsItem'] NDialogProvider: typeof import('naive-ui')['NDialogProvider'] NDivider: typeof import('naive-ui')['NDivider'] NDrawer: typeof import('naive-ui')['NDrawer'] @@ -52,7 +42,6 @@ declare module 'vue' { NEmpty: typeof import('naive-ui')['NEmpty'] NForm: typeof import('naive-ui')['NForm'] NFormItem: typeof import('naive-ui')['NFormItem'] - NFormItemGi: typeof import('naive-ui')['NFormItemGi'] NGi: typeof import('naive-ui')['NGi'] NGrid: typeof import('naive-ui')['NGrid'] NInput: typeof import('naive-ui')['NInput'] @@ -65,10 +54,6 @@ declare module 'vue' { NMessageProvider: typeof import('naive-ui')['NMessageProvider'] NModal: typeof import('naive-ui')['NModal'] NNotificationProvider: typeof import('naive-ui')['NNotificationProvider'] - NPopconfirm: typeof import('naive-ui')['NPopconfirm'] - NPopover: typeof import('naive-ui')['NPopover'] - NRadio: typeof import('naive-ui')['NRadio'] - NRadioGroup: typeof import('naive-ui')['NRadioGroup'] NScrollbar: typeof import('naive-ui')['NScrollbar'] NSelect: typeof import('naive-ui')['NSelect'] NSpace: typeof import('naive-ui')['NSpace'] @@ -76,7 +61,6 @@ declare module 'vue' { NSwitch: typeof import('naive-ui')['NSwitch'] NTab: typeof import('naive-ui')['NTab'] NTabs: typeof import('naive-ui')['NTabs'] - NTag: typeof import('naive-ui')['NTag'] NThing: typeof import('naive-ui')['NThing'] NTooltip: typeof import('naive-ui')['NTooltip'] PinToggler: typeof import('./../components/common/pin-toggler.vue')['default'] diff --git a/src/typings/storage.d.ts b/src/typings/storage.d.ts index c9ea420..e47cff0 100644 --- a/src/typings/storage.d.ts +++ b/src/typings/storage.d.ts @@ -14,6 +14,8 @@ declare namespace StorageType { lang: App.I18n.LangType; /** The token */ token: string; + /** The namespace id */ + namespaceId: string; /** The refresh token */ refreshToken: string; /** The user info */ diff --git a/src/views/_builtin/login/modules/pwd-login.vue b/src/views/_builtin/login/modules/pwd-login.vue index 8ba229d..06c520d 100644 --- a/src/views/_builtin/login/modules/pwd-login.vue +++ b/src/views/_builtin/login/modules/pwd-login.vue @@ -1,5 +1,6 @@ diff --git a/src/views/home/modules/header-banner.vue b/src/views/home/modules/header-banner.vue index 42da042..daf3a30 100644 --- a/src/views/home/modules/header-banner.vue +++ b/src/views/home/modules/header-banner.vue @@ -48,7 +48,7 @@ const statisticData = computed(() => [

- {{ $t('page.home.greeting', { userName: authStore.userInfo.userName }) }} + {{ $t('page.home.greeting', { userName: authStore.userInfo.username }) }}

{{ $t('page.home.weatherDesc') }}