Commit ce33b5c2197893c5b0e43a3112195bc62cab4f69
Committed by
Gitee
!283 fix:vue3 bug
Merge pull request !283 from weikun/master
Showing
11 changed files
with
86 additions
and
50 deletions
yudao-ui-admin-vue3/.vscode/settings.json
| @@ -39,5 +39,6 @@ | @@ -39,5 +39,6 @@ | ||
| 39 | "i18n-ally.sourceLanguage": "en", | 39 | "i18n-ally.sourceLanguage": "en", |
| 40 | "i18n-ally.displayLanguage": "zh-CN", | 40 | "i18n-ally.displayLanguage": "zh-CN", |
| 41 | "i18n-ally.enabledFrameworks": ["vue", "react"], | 41 | "i18n-ally.enabledFrameworks": ["vue", "react"], |
| 42 | - "god.tsconfig": "./tsconfig.json" | 42 | + "god.tsconfig": "./tsconfig.json", |
| 43 | + "vue-i18n.i18nPaths": "src/locales" | ||
| 43 | } | 44 | } |
yudao-ui-admin-vue3/package.json
| @@ -38,6 +38,7 @@ | @@ -38,6 +38,7 @@ | ||
| 38 | "echarts-wordcloud": "^2.0.0", | 38 | "echarts-wordcloud": "^2.0.0", |
| 39 | "element-plus": "2.2.18", | 39 | "element-plus": "2.2.18", |
| 40 | "intro.js": "^6.0.0", | 40 | "intro.js": "^6.0.0", |
| 41 | + "js-cookie": "^3.0.1", | ||
| 41 | "jsencrypt": "^3.2.1", | 42 | "jsencrypt": "^3.2.1", |
| 42 | "lodash-es": "^4.17.21", | 43 | "lodash-es": "^4.17.21", |
| 43 | "mitt": "^3.0.0", | 44 | "mitt": "^3.0.0", |
yudao-ui-admin-vue3/src/App.vue
| @@ -4,7 +4,7 @@ import { useAppStore } from '@/store/modules/app' | @@ -4,7 +4,7 @@ import { useAppStore } from '@/store/modules/app' | ||
| 4 | import { ConfigGlobal } from '@/components/ConfigGlobal' | 4 | import { ConfigGlobal } from '@/components/ConfigGlobal' |
| 5 | import { isDark } from '@/utils/is' | 5 | import { isDark } from '@/utils/is' |
| 6 | import { useDesign } from '@/hooks/web/useDesign' | 6 | import { useDesign } from '@/hooks/web/useDesign' |
| 7 | -import { useCache } from '@/hooks/web/useCache' | 7 | +import Cookies from 'js-cookie' |
| 8 | 8 | ||
| 9 | const { getPrefixCls } = useDesign() | 9 | const { getPrefixCls } = useDesign() |
| 10 | 10 | ||
| @@ -16,18 +16,19 @@ const currentSize = computed(() => appStore.getCurrentSize) | @@ -16,18 +16,19 @@ const currentSize = computed(() => appStore.getCurrentSize) | ||
| 16 | 16 | ||
| 17 | const greyMode = computed(() => appStore.getGreyMode) | 17 | const greyMode = computed(() => appStore.getGreyMode) |
| 18 | 18 | ||
| 19 | -const { wsCache } = useCache() | ||
| 20 | - | ||
| 21 | // 根据浏览器当前主题设置系统主题色 | 19 | // 根据浏览器当前主题设置系统主题色 |
| 22 | const setDefaultTheme = () => { | 20 | const setDefaultTheme = () => { |
| 23 | - if (wsCache.get('isDark')) { | ||
| 24 | - appStore.setIsDark(wsCache.get('isDark')) | 21 | + if (Cookies.get('isDark')) { |
| 22 | + if (Cookies.get('isDark') === 'true') { | ||
| 23 | + appStore.setIsDark(true) | ||
| 24 | + } else { | ||
| 25 | + appStore.setIsDark(false) | ||
| 26 | + } | ||
| 25 | return | 27 | return |
| 26 | } | 28 | } |
| 27 | const isDarkTheme = isDark() | 29 | const isDarkTheme = isDark() |
| 28 | appStore.setIsDark(isDarkTheme) | 30 | appStore.setIsDark(isDarkTheme) |
| 29 | } | 31 | } |
| 30 | - | ||
| 31 | setDefaultTheme() | 32 | setDefaultTheme() |
| 32 | </script> | 33 | </script> |
| 33 | 34 |
yudao-ui-admin-vue3/src/api/system/user/profile/index.ts
| @@ -16,7 +16,7 @@ export const updateUserProfileApi = (params) => { | @@ -16,7 +16,7 @@ export const updateUserProfileApi = (params) => { | ||
| 16 | export const updateUserPwdApi = (oldPassword: string, newPassword: string) => { | 16 | export const updateUserPwdApi = (oldPassword: string, newPassword: string) => { |
| 17 | return request.put({ | 17 | return request.put({ |
| 18 | url: '/system/user/profile/update-password', | 18 | url: '/system/user/profile/update-password', |
| 19 | - params: { | 19 | + data: { |
| 20 | oldPassword: oldPassword, | 20 | oldPassword: oldPassword, |
| 21 | newPassword: newPassword | 21 | newPassword: newPassword |
| 22 | } | 22 | } |
yudao-ui-admin-vue3/src/config/axios/index.ts
| @@ -96,6 +96,7 @@ service.interceptors.request.use( | @@ -96,6 +96,7 @@ service.interceptors.request.use( | ||
| 96 | service.interceptors.response.use( | 96 | service.interceptors.response.use( |
| 97 | async (response: AxiosResponse<Recordable>) => { | 97 | async (response: AxiosResponse<Recordable>) => { |
| 98 | const { data } = response | 98 | const { data } = response |
| 99 | + const config = response.config | ||
| 99 | if (!data) { | 100 | if (!data) { |
| 100 | // 返回“[HTTP]请求没有返回值”; | 101 | // 返回“[HTTP]请求没有返回值”; |
| 101 | throw new Error() | 102 | throw new Error() |
| @@ -127,13 +128,13 @@ service.interceptors.response.use( | @@ -127,13 +128,13 @@ service.interceptors.response.use( | ||
| 127 | try { | 128 | try { |
| 128 | const refreshTokenRes = await refreshToken() | 129 | const refreshTokenRes = await refreshToken() |
| 129 | // 2.1 刷新成功,则回放队列的请求 + 当前请求 | 130 | // 2.1 刷新成功,则回放队列的请求 + 当前请求 |
| 130 | - setToken(refreshTokenRes.data) | ||
| 131 | - ;(config as Recordable).headers.Authorization = 'Bearer ' + getAccessToken() | 131 | + setToken(refreshTokenRes.data.data) |
| 132 | + config.headers!.Authorization = 'Bearer ' + getAccessToken() | ||
| 132 | requestList.forEach((cb: any) => { | 133 | requestList.forEach((cb: any) => { |
| 133 | cb() | 134 | cb() |
| 134 | }) | 135 | }) |
| 135 | requestList = [] | 136 | requestList = [] |
| 136 | - return service(response.config) | 137 | + return service(config) |
| 137 | } catch (e) { | 138 | } catch (e) { |
| 138 | // 为什么需要 catch 异常呢?刷新失败时,请求因为 Promise.reject 触发异常。 | 139 | // 为什么需要 catch 异常呢?刷新失败时,请求因为 Promise.reject 触发异常。 |
| 139 | // 2.2 刷新失败,只回放队列的请求 | 140 | // 2.2 刷新失败,只回放队列的请求 |
| @@ -150,8 +151,8 @@ service.interceptors.response.use( | @@ -150,8 +151,8 @@ service.interceptors.response.use( | ||
| 150 | // 添加到队列,等待刷新获取到新的令牌 | 151 | // 添加到队列,等待刷新获取到新的令牌 |
| 151 | return new Promise((resolve) => { | 152 | return new Promise((resolve) => { |
| 152 | requestList.push(() => { | 153 | requestList.push(() => { |
| 153 | - ;(config as Recordable).headers.Authorization = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token 请根据实际情况自行修改 | ||
| 154 | - resolve(service(response.config)) | 154 | + config.headers!.Authorization = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token 请根据实际情况自行修改 |
| 155 | + resolve(service(config)) | ||
| 155 | }) | 156 | }) |
| 156 | }) | 157 | }) |
| 157 | } | 158 | } |
yudao-ui-admin-vue3/src/styles/var.css
yudao-ui-admin-vue3/src/utils/jsencrypt.ts
yudao-ui-admin-vue3/src/utils/routerHelper.ts
| @@ -65,30 +65,49 @@ export const generateRoute = (routes: AppCustomRouteRecordRaw[]): AppRouteRecord | @@ -65,30 +65,49 @@ export const generateRoute = (routes: AppCustomRouteRecordRaw[]): AppRouteRecord | ||
| 65 | redirect: route.redirect, | 65 | redirect: route.redirect, |
| 66 | meta: meta | 66 | meta: meta |
| 67 | } | 67 | } |
| 68 | - // 目录 | ||
| 69 | - if (route.children) { | 68 | + //处理顶级非目录路由 |
| 69 | + if (!route.children && route.parentId == 0 && route.component) { | ||
| 70 | data.component = Layout | 70 | data.component = Layout |
| 71 | - data.redirect = getRedirect(route.path, route.children) | ||
| 72 | - // 外链 | ||
| 73 | - } else if (isUrl(route.path)) { | ||
| 74 | - data = { | ||
| 75 | - path: '/external-link', | ||
| 76 | - component: Layout, | ||
| 77 | - meta: { | ||
| 78 | - name: route.name | ||
| 79 | - }, | ||
| 80 | - children: [data] | ||
| 81 | - } as AppRouteRecordRaw | ||
| 82 | - // 菜单 | ||
| 83 | - } else { | ||
| 84 | - // 对后端传component组件路径和不传做兼容(如果后端传component组件路径,那么path可以随便写,如果不传,component组件路径会根path保持一致) | 71 | + data.meta = {} |
| 72 | + data.name = toCamelCase(route.path, true) + 'Parent' | ||
| 73 | + data.redirect = '' | ||
| 74 | + const childrenData: AppRouteRecordRaw = { | ||
| 75 | + path: '', | ||
| 76 | + name: toCamelCase(route.path, true), | ||
| 77 | + redirect: route.redirect, | ||
| 78 | + meta: meta | ||
| 79 | + } | ||
| 85 | const index = route?.component | 80 | const index = route?.component |
| 86 | ? modulesRoutesKeys.findIndex((ev) => ev.includes(route.component)) | 81 | ? modulesRoutesKeys.findIndex((ev) => ev.includes(route.component)) |
| 87 | : modulesRoutesKeys.findIndex((ev) => ev.includes(route.path)) | 82 | : modulesRoutesKeys.findIndex((ev) => ev.includes(route.path)) |
| 88 | - data.component = modules[modulesRoutesKeys[index]] | ||
| 89 | - } | ||
| 90 | - if (route.children) { | ||
| 91 | - data.children = generateRoute(route.children) | 83 | + childrenData.component = modules[modulesRoutesKeys[index]] |
| 84 | + data.children = [childrenData] | ||
| 85 | + } else { | ||
| 86 | + // 目录 | ||
| 87 | + if (route.children) { | ||
| 88 | + data.component = Layout | ||
| 89 | + data.redirect = getRedirect(route.path, route.children) | ||
| 90 | + // 外链 | ||
| 91 | + } else if (isUrl(route.path)) { | ||
| 92 | + data = { | ||
| 93 | + path: '/external-link', | ||
| 94 | + component: Layout, | ||
| 95 | + meta: { | ||
| 96 | + name: route.name | ||
| 97 | + }, | ||
| 98 | + children: [data] | ||
| 99 | + } as AppRouteRecordRaw | ||
| 100 | + // 菜单 | ||
| 101 | + } else { | ||
| 102 | + // 对后端传component组件路径和不传做兼容(如果后端传component组件路径,那么path可以随便写,如果不传,component组件路径会根path保持一致) | ||
| 103 | + const index = route?.component | ||
| 104 | + ? modulesRoutesKeys.findIndex((ev) => ev.includes(route.component)) | ||
| 105 | + : modulesRoutesKeys.findIndex((ev) => ev.includes(route.path)) | ||
| 106 | + data.component = modules[modulesRoutesKeys[index]] | ||
| 107 | + } | ||
| 108 | + if (route.children) { | ||
| 109 | + data.children = generateRoute(route.children) | ||
| 110 | + } | ||
| 92 | } | 111 | } |
| 93 | res.push(data) | 112 | res.push(data) |
| 94 | } | 113 | } |
yudao-ui-admin-vue3/src/views/Login/components/LoginForm.vue
| @@ -13,14 +13,7 @@ import { | @@ -13,14 +13,7 @@ import { | ||
| 13 | } from 'element-plus' | 13 | } from 'element-plus' |
| 14 | import { reactive, ref, unref, onMounted, computed, watch } from 'vue' | 14 | import { reactive, ref, unref, onMounted, computed, watch } from 'vue' |
| 15 | import * as LoginApi from '@/api/login' | 15 | import * as LoginApi from '@/api/login' |
| 16 | -import { | ||
| 17 | - setToken, | ||
| 18 | - setTenantId, | ||
| 19 | - getUsername, | ||
| 20 | - getRememberMe, | ||
| 21 | - getPassword, | ||
| 22 | - getTenantName | ||
| 23 | -} from '@/utils/auth' | 16 | +import { setToken, setTenantId } from '@/utils/auth' |
| 24 | import { usePermissionStore } from '@/store/modules/permission' | 17 | import { usePermissionStore } from '@/store/modules/permission' |
| 25 | import { useRouter } from 'vue-router' | 18 | import { useRouter } from 'vue-router' |
| 26 | import { useI18n } from '@/hooks/web/useI18n' | 19 | import { useI18n } from '@/hooks/web/useI18n' |
| @@ -29,6 +22,8 @@ import { Icon } from '@/components/Icon' | @@ -29,6 +22,8 @@ import { Icon } from '@/components/Icon' | ||
| 29 | import { LoginStateEnum, useLoginState, useFormValid } from './useLogin' | 22 | import { LoginStateEnum, useLoginState, useFormValid } from './useLogin' |
| 30 | import type { RouteLocationNormalizedLoaded } from 'vue-router' | 23 | import type { RouteLocationNormalizedLoaded } from 'vue-router' |
| 31 | import { Verify } from '@/components/Verifition' | 24 | import { Verify } from '@/components/Verifition' |
| 25 | +import Cookies from 'js-cookie' | ||
| 26 | +import { decrypt, encrypt } from '@/utils/jsencrypt' | ||
| 32 | 27 | ||
| 33 | const { currentRoute, push } = useRouter() | 28 | const { currentRoute, push } = useRouter() |
| 34 | const permissionStore = usePermissionStore() | 29 | const permissionStore = usePermissionStore() |
| @@ -72,7 +67,7 @@ const captchaType = ref('blockPuzzle') | @@ -72,7 +67,7 @@ const captchaType = ref('blockPuzzle') | ||
| 72 | // 获取验证码 | 67 | // 获取验证码 |
| 73 | const getCode = async () => { | 68 | const getCode = async () => { |
| 74 | // 情况一,未开启:则直接登录 | 69 | // 情况一,未开启:则直接登录 |
| 75 | - if (!loginData.captchaEnable) { | 70 | + if (loginData.captchaEnable === 'false') { |
| 76 | await handleLogin({}) | 71 | await handleLogin({}) |
| 77 | return | 72 | return |
| 78 | } | 73 | } |
| @@ -88,15 +83,15 @@ const getTenantId = async () => { | @@ -88,15 +83,15 @@ const getTenantId = async () => { | ||
| 88 | } | 83 | } |
| 89 | // 记住我 | 84 | // 记住我 |
| 90 | const getCookie = () => { | 85 | const getCookie = () => { |
| 91 | - const username = getUsername() | ||
| 92 | - const password = getPassword() | ||
| 93 | - const rememberMe = getRememberMe() | ||
| 94 | - const tenantName = getTenantName() | 86 | + const username = Cookies.get('username') |
| 87 | + const password = Cookies.get('password') ? decrypt(Cookies.get('password')) : undefined | ||
| 88 | + const rememberMe = Cookies.get('rememberMe') | ||
| 89 | + const tenantName = Cookies.get('tenantName') | ||
| 95 | loginData.loginForm = { | 90 | loginData.loginForm = { |
| 96 | ...loginData.loginForm, | 91 | ...loginData.loginForm, |
| 97 | username: username ? username : loginData.loginForm.username, | 92 | username: username ? username : loginData.loginForm.username, |
| 98 | password: password ? password : loginData.loginForm.password, | 93 | password: password ? password : loginData.loginForm.password, |
| 99 | - rememberMe: rememberMe ? getRememberMe() : false, | 94 | + rememberMe: rememberMe ? true : false, |
| 100 | tenantName: tenantName ? tenantName : loginData.loginForm.tenantName | 95 | tenantName: tenantName ? tenantName : loginData.loginForm.tenantName |
| 101 | } | 96 | } |
| 102 | } | 97 | } |
| @@ -114,6 +109,17 @@ const handleLogin = async (params) => { | @@ -114,6 +109,17 @@ const handleLogin = async (params) => { | ||
| 114 | if (!res) { | 109 | if (!res) { |
| 115 | return | 110 | return |
| 116 | } | 111 | } |
| 112 | + if (loginData.loginForm.rememberMe) { | ||
| 113 | + Cookies.set('username', loginData.loginForm.username, { expires: 30 }) | ||
| 114 | + Cookies.set('password', encrypt(loginData.loginForm.password), { expires: 30 }) | ||
| 115 | + Cookies.set('rememberMe', loginData.loginForm.rememberMe, { expires: 30 }) | ||
| 116 | + Cookies.set('tenantName', loginData.loginForm.tenantName, { expires: 30 }) | ||
| 117 | + } else { | ||
| 118 | + Cookies.remove('username') | ||
| 119 | + Cookies.remove('password') | ||
| 120 | + Cookies.remove('rememberMe') | ||
| 121 | + Cookies.remove('tenantName') | ||
| 122 | + } | ||
| 117 | setToken(res) | 123 | setToken(res) |
| 118 | if (!redirect.value) { | 124 | if (!redirect.value) { |
| 119 | redirect.value = '/' | 125 | redirect.value = '/' |
yudao-ui-admin-vue3/types/env.d.ts
| @@ -11,8 +11,8 @@ interface ImportMetaEnv { | @@ -11,8 +11,8 @@ interface ImportMetaEnv { | ||
| 11 | readonly VITE_APP_TITLE: string | 11 | readonly VITE_APP_TITLE: string |
| 12 | readonly VITE_PORT: number | 12 | readonly VITE_PORT: number |
| 13 | readonly VITE_OPEN: boolean | 13 | readonly VITE_OPEN: boolean |
| 14 | - readonly VITE_APP_CAPTCHA_ENABLE: boolean | ||
| 15 | - readonly VITE_APP_TENANT_ENABLE: boolean | 14 | + readonly VITE_APP_CAPTCHA_ENABLE: string |
| 15 | + readonly VITE_APP_TENANT_ENABLE: string | ||
| 16 | readonly VITE_BASE_URL: string | 16 | readonly VITE_BASE_URL: string |
| 17 | readonly VITE_UPLOAD_URL: string | 17 | readonly VITE_UPLOAD_URL: string |
| 18 | readonly VITE_API_BASEPATH: string | 18 | readonly VITE_API_BASEPATH: string |
yudao-ui-admin-vue3/types/router.d.ts