From 31a2e46d4bbe4f34ce9dd1f4391902b29dd3d8f1 Mon Sep 17 00:00:00 2001 From: whq <460794335@qq.com> Date: Thu, 30 Mar 2023 16:45:56 +0800 Subject: [PATCH] =?UTF-8?q?=E7=99=BB=E5=BD=95=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 5 +- src/api/login/index.js | 17 ++- src/api/system/user.js | 51 ++++++++ src/layout/navBars/breadcrumb/user.vue | 21 +++- src/stores/themeConfig.js | 6 + src/stores/userInfo.js | 87 ++++++++------ src/utils/request.js | 12 +- src/views/login/component/account.vue | 155 ++++++++++++++++--------- src/views/login/index.vue | 2 +- vite.config.js | 2 +- yarn.lock | 5 + 11 files changed, 258 insertions(+), 105 deletions(-) create mode 100644 src/api/system/user.js diff --git a/package.json b/package.json index b2adea0..5826b57 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "vue-next-admin-template-js", + "name": "vordm", "version": "2.4.32", "description": "vue3 vite next admin template js setup", "author": "lyt_20201208", @@ -15,16 +15,17 @@ "echarts": "^5.4.2", "element-plus": "^2.3.1", "js-cookie": "^3.0.1", + "js-md5": "^0.7.3", "mitt": "^3.0.0", "nprogress": "^0.2.0", "pinia": "^2.0.33", "qrcodejs2-fixes": "^0.0.2", + "qs": "^6.11.1", "screenfull": "^6.0.2", "sortablejs": "^1.15.0", "vue": "^3.2.47", "vue-clipboard3": "^2.0.0", "vue-demi": "^0.13.11", - "qs": "^6.11.1", "vue-router": "^4.1.6" }, "devDependencies": { diff --git a/src/api/login/index.js b/src/api/login/index.js index 4263c97..7da26b5 100644 --- a/src/api/login/index.js +++ b/src/api/login/index.js @@ -1,4 +1,5 @@ import request from '/@/utils/request'; +import qs from 'qs' /** * (不建议写成 request.post(xxx),因为这样 post 时,无法 params 与 data 同时传参) @@ -9,14 +10,14 @@ import request from '/@/utils/request'; */ export function useLoginApi() { return { - signInByUsername: ({tenantId, deptId, roleId, username, password, type, key, code}) => { + signInByUsername: ({tenantId, deptId, roleId, username, password, type, key, code, grantType}) => { return request({ - url: '/api/blade-auth/oauth/token', + url: '/api/system-manager/oauth/token', method: 'post', headers: { 'Tenant-Id': tenantId, - 'Dept-Id': '', - 'Role-Id': '', + 'Dept-Id': deptId, + 'Role-Id': roleId, 'Captcha-Key': key, 'Captcha-Code': code, 'Content-Type': 'application/x-www-form-urlencoded', @@ -25,7 +26,7 @@ export function useLoginApi() { tenantId, username, password, - grant_type: "captcha", + grant_type: grantType, deptId, roleId, scope: "all", @@ -34,6 +35,12 @@ export function useLoginApi() { }); }, + //获取验证码 + getCaptcha: () => request({ + url: '/api/system-manager/oauth/captcha', + method: 'get', + }), + signOut: (data) => { return request({ url: '/user/signOut', diff --git a/src/api/system/user.js b/src/api/system/user.js new file mode 100644 index 0000000..c382a05 --- /dev/null +++ b/src/api/system/user.js @@ -0,0 +1,51 @@ +import request from '/@/utils/request'; +import qs from 'qs'; + +export const getUserInfo = () => { + return request({ + url: '/api/system-manager/user/info', + method: 'get', + }) +} + +export const resetPassword = (userIds) => { + return request({ + url: '/api/system-manager/user/reset-password', + method: 'post', + params: { + userIds, + } + }) +} + +export const updatePassword = (oldPassword, newPassword, newPassword1) => { + return request({ + url: '/api/system-manager/user/update-password', + method: 'post', + params: { + oldPassword, + newPassword, + newPassword1, + } + }) +} + +export const getButtons = () => request({ + url: '/api/system-manager/menu/buttons', + method: 'get' +}); + +export const refreshToken = (refresh_token, tenantId) => request({ + url: '/api/system-manager/oauth/token', + method: 'post', + headers: { + 'Tenant-Id': tenantId, + 'Content-Type': 'application/x-www-form-urlencoded', + }, + data: qs.stringify({ + tenantId, + refresh_token, + grant_type: "refresh_token", + scope: "all", + }) +}); \ No newline at end of file diff --git a/src/layout/navBars/breadcrumb/user.vue b/src/layout/navBars/breadcrumb/user.vue index 245fdf7..f84f661 100644 --- a/src/layout/navBars/breadcrumb/user.vue +++ b/src/layout/navBars/breadcrumb/user.vue @@ -73,7 +73,7 @@ import { useUserInfo } from '/@/stores/userInfo'; import { useThemeConfig } from '/@/stores/themeConfig'; import mittBus from '/@/utils/mitt'; import { Session, Local } from '/@/utils/storage'; - +import { refreshToken } from '/@/api/system/user.js' // 引入组件 const UserNews = defineAsyncComponent(() => import('/@/layout/navBars/breadcrumb/userNews.vue')); const Search = defineAsyncComponent(() => import('/@/layout/navBars/breadcrumb/search.vue')); @@ -83,11 +83,13 @@ const router = useRouter(); const stores = useUserInfo(); const storesThemeConfig = useThemeConfig(); const { userInfos } = storeToRefs(stores); -const { themeConfig } = storeToRefs(storesThemeConfig); +const { themeConfig, website } = storeToRefs(storesThemeConfig); + const searchRef = ref(); const state = reactive({ isScreenfull: false, disabledSize: 'large', + setIntervalId: null }); // 设置分割样式 @@ -145,6 +147,7 @@ const onHandleCommandClick = (path) => { .then(async () => { // 清除缓存/token等 Session.clear(); + clearInterval(state.setIntervalId); // 使用 reload 时,不需要调用 resetRoute() 重置路由 window.location.reload(); }) @@ -176,6 +179,20 @@ onMounted(() => { if (Local.get('themeConfig')) { initI18nOrSize('globalComponentSize', 'disabledSize'); } + //刷新token + state.setIntervalId =setInterval(() => { + const dateTime = Session.get('token-time'); + const rt = Session.get('refresh-token'); + const now = new Date().getTime(); + if((now - dateTime) / 1000 > website.value.tokenTime){ + // 刷新token + refreshToken(rt, website.value.tenantId).then(res=>{ + Session.set('token', res.access_token); + Session.set('token-time', new Date().getTime()); + Session.set('refresh-token', res.refresh_token); + }) + } + },10000); }); diff --git a/src/stores/themeConfig.js b/src/stores/themeConfig.js index f7931be..05b5810 100644 --- a/src/stores/themeConfig.js +++ b/src/stores/themeConfig.js @@ -10,6 +10,12 @@ import { defineStore } from 'pinia'; */ export const useThemeConfig = defineStore('themeConfig', { state: () => ({ + website: { + // 开启验证码模式 + captchaMode: false, + tokenTime: 3000, + tenantId: '595035' + }, themeConfig: { // 是否开启布局配置抽屉 isDrawer: false, diff --git a/src/stores/userInfo.js b/src/stores/userInfo.js index 54da15f..9b983ab 100644 --- a/src/stores/userInfo.js +++ b/src/stores/userInfo.js @@ -1,7 +1,6 @@ import { defineStore } from 'pinia'; -import Cookies from 'js-cookie'; import { Session } from '/@/utils/storage'; - +import { getUserInfo, getButtons } from '/@/api/system/user.js' /** * 用户信息 * @methods setUserInfos 设置用户信息 @@ -26,47 +25,67 @@ export const useUserInfo = defineStore('userInfo', { this.userInfos = userInfos; } }, + async Buttons() { + return new Promise((resolve) => { + getButtons().then(data => { + console.log(data) + resolve(this.formatBtns(data)); + }) + }) + }, + + formatBtns(data) { + let map = []; + data.forEach(item => { + map.push(item.code) + //判断是否存在子菜单 + if (item.children) { + map = map.concat(this.formatBtns(item.children)); + } + }) + return map; + }, // 模拟接口数据 // https://gitee.com/lyt-top/vue-next-admin/issues/I5F1HP async getApiUserInfo() { return new Promise((resolve) => { - setTimeout(() => { - // 模拟数据,请求接口时,记得删除多余代码及对应依赖的引入 - const userName = Cookies.get('userName'); - // 模拟数据 - let defaultRoles = []; - let defaultAuthBtnList = []; - // admin 页面权限标识,对应路由 meta.roles,用于控制路由的显示/隐藏 - let adminRoles = ['admin']; - // admin 按钮权限标识 - let adminAuthBtnList = ['btn.add', 'btn.del', 'btn.edit', 'btn.link']; - // test 页面权限标识,对应路由 meta.roles,用于控制路由的显示/隐藏 - let testRoles = ['common']; - // test 按钮权限标识 - let testAuthBtnList = ['btn.add', 'btn.link']; - // 不同用户模拟不同的用户权限 - if (userName === 'admin') { - defaultRoles = adminRoles; - defaultAuthBtnList = adminAuthBtnList; - } else { - defaultRoles = testRoles; - defaultAuthBtnList = testAuthBtnList; - } - // 用户信息模拟数据 + // 获取用户信息 + getUserInfo().then((user) => { + const arr = []; + arr.push(user.roleName); const userInfos = { - userName: userName, - photo: - userName === 'admin' - ? 'https://img2.baidu.com/it/u=1978192862,2048448374&fm=253&fmt=auto&app=138&f=JPEG?w=504&h=500' - : 'https://img2.baidu.com/it/u=2370931438,70387529&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500', + userName: user.account, + photo: user.account === 'admin' + ? 'https://img2.baidu.com/it/u=1978192862,2048448374&fm=253&fmt=auto&app=138&f=JPEG?w=504&h=500' + : 'https://img2.baidu.com/it/u=2370931438,70387529&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500', time: new Date().getTime(), - roles: defaultRoles, - authBtnList: defaultAuthBtnList, + roles: arr, + authBtnList: [], + ...user }; + // 存储用户信息到浏览器缓存 Session.set('userInfo', userInfos); - resolve(userInfos); - }, 0); + resolve(userInfos) + // 获取权限按钮 + // this.Buttons().then((res2) => { + // // 用户信息模拟数据 + // const userInfos = { + // userName: user.account, + // photo: user.account === 'admin' + // ? 'https://img2.baidu.com/it/u=1978192862,2048448374&fm=253&fmt=auto&app=138&f=JPEG?w=504&h=500' + // : 'https://img2.baidu.com/it/u=2370931438,70387529&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500', + // time: new Date().getTime(), + // roles: arr, + // authBtnList: res2, + // ...user + // }; + // // 存储用户信息到浏览器缓存 + // Session.set('userInfo', userInfos); + // resolve(userInfos) + // }) + }); }); + }, }, }); diff --git a/src/utils/request.js b/src/utils/request.js index f86c808..39b06a6 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -18,9 +18,10 @@ const service = axios.create({ // 添加请求拦截器 service.interceptors.request.use( (config) => { + config.headers['Authorization'] = 'Basic Vm9SRE1BZG1pbjp2b3JkbV9hZG1pbl9zZWNyZXQ='; // 在发送请求之前做些什么 token if (Session.get('token')) { - config.headers['Authorization'] = `${Session.get('token')}`; + config.headers['Blade-Auth'] = `Bearer ${Session.get('token')}`; } return config; }, @@ -35,7 +36,7 @@ service.interceptors.response.use( (response) => { // 对响应数据做点什么 const res = response.data; - if (res.code && res.code !== 0) { + if (res.code && res.code !== 200) { // `token` 过期或者账号已在别处登录 if (res.code === 401 || res.code === 4001) { Session.clear(); // 清除浏览器全部临时缓存 @@ -43,10 +44,12 @@ service.interceptors.response.use( ElMessageBox.alert('你已被登出,请重新登录', '提示', {}) .then(() => {}) .catch(() => {}); + } else if(res.code === 400){ + ElMessage.error(res.msg) } return Promise.reject(service.interceptors.response); } else { - return res; + return res.data || res; } }, (error) => { @@ -56,7 +59,8 @@ service.interceptors.response.use( } else if (error.message == 'Network Error') { ElMessage.error('网络连接错误'); } else { - if (error.response.data) ElMessage.error(error.response.statusText); + if( error.response.data.error_description ) ElMessage.error(error.response.data.error_description); + //if (error.response.data) ElMessage.error(error.response.statusText); else ElMessage.error('接口路径找不到'); } return Promise.reject(error); diff --git a/src/views/login/component/account.vue b/src/views/login/component/account.vue index e824e81..3171e20 100644 --- a/src/views/login/component/account.vue +++ b/src/views/login/component/account.vue @@ -1,14 +1,14 @@ - + - + - - + + + diff --git a/src/views/login/index.vue b/src/views/login/index.vue index 6438f18..04915af 100644 --- a/src/views/login/index.vue +++ b/src/views/login/index.vue @@ -22,7 +22,7 @@
- + diff --git a/vite.config.js b/vite.config.js index c30f713..f7632fb 100644 --- a/vite.config.js +++ b/vite.config.js @@ -30,7 +30,7 @@ const viteConfig = defineConfig((mode) => { hmr: true, proxy: { '/api': { - target: 'https://gitee.com', + target: 'http://192.168.31.14:9090', ws: true, changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, ''), diff --git a/yarn.lock b/yarn.lock index c91ddeb..9f48e5c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1021,6 +1021,11 @@ js-cookie@^3.0.1: resolved "https://registry.npmmirror.com/js-cookie/-/js-cookie-3.0.1.tgz#9e39b4c6c2f56563708d7d31f6f5f21873a92414" integrity sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw== +js-md5@^0.7.3: + version "0.7.3" + resolved "https://registry.npmmirror.com/js-md5/-/js-md5-0.7.3.tgz#b4f2fbb0b327455f598d6727e38ec272cd09c3f2" + integrity sha512-ZC41vPSTLKGwIRjqDh8DfXoCrdQIyBgspJVPXHBGu4nZlAEvG3nf+jO9avM9RmLiGakg7vz974ms99nEV0tmTQ== + js-sdsl@^4.1.4: version "4.4.0" resolved "https://registry.npmmirror.com/js-sdsl/-/js-sdsl-4.4.0.tgz#8b437dbe642daa95760400b602378ed8ffea8430"