style:合并dev
Showing
11 changed files
with
195 additions
and
51 deletions
| 1 | <!-- | 1 | <!-- |
| 2 | * @Description: | 2 | * @Description: |
| 3 | * @Autor: renchao | 3 | * @Autor: renchao |
| 4 | * @LastEditTime: 2023-05-30 15:08:51 | 4 | * @LastEditTime: 2023-05-31 15:33:18 |
| 5 | --> | 5 | --> |
| 6 | <!DOCTYPE html> | 6 | <!DOCTYPE html> |
| 7 | <html> | 7 | <html> |
| ... | @@ -19,7 +19,19 @@ | ... | @@ -19,7 +19,19 @@ |
| 19 | </head> | 19 | </head> |
| 20 | <script> | 20 | <script> |
| 21 | window.baseUrl = location.origin || location.protocol + '//' + location.host | 21 | window.baseUrl = location.origin || location.protocol + '//' + location.host |
| 22 | const authorization = "bearer ATT-7-TiYJVcoDnfhNGs160E6MbQ-QA9Ot3Tby" | 22 | window._config = { |
| 23 | // 是否微服务模式,业务系统根据需要读取 | ||
| 24 | cloudEnable: false, | ||
| 25 | // 是否启用单点登录 | ||
| 26 | casEnable: true, | ||
| 27 | // cas 基地址 | ||
| 28 | casBaseURL: 'http://192.168.2.38/cas', | ||
| 29 | services: { | ||
| 30 | // 配置到 contextPath 前一级 | ||
| 31 | management: 'http://192.168.2.38', | ||
| 32 | business: 'http://localhost:7001' | ||
| 33 | } | ||
| 34 | } | ||
| 23 | fetch('<%= BASE_URL %>config.json') | 35 | fetch('<%= BASE_URL %>config.json') |
| 24 | .then(response => response.json()) | 36 | .then(response => response.json()) |
| 25 | .then(config => { | 37 | .then(config => { | ... | ... |
| ... | @@ -27,6 +27,7 @@ | ... | @@ -27,6 +27,7 @@ |
| 27 | </div> | 27 | </div> |
| 28 | </template> | 28 | </template> |
| 29 | <script> | 29 | <script> |
| 30 | import axios from 'axios' | ||
| 30 | import { mapGetters } from 'vuex' | 31 | import { mapGetters } from 'vuex' |
| 31 | import NoticeBar from '@/components/NoticeBar/index' | 32 | import NoticeBar from '@/components/NoticeBar/index' |
| 32 | import { | 33 | import { |
| ... | @@ -72,9 +73,20 @@ | ... | @@ -72,9 +73,20 @@ |
| 72 | }) | 73 | }) |
| 73 | }, | 74 | }, |
| 74 | logout () { | 75 | logout () { |
| 75 | const url = baseUrl + "/sso-logout?redirect_uri=" + baseUrl + "/bdcdj"; | 76 | axios.post(this.BASE_API.ip + "/management/logout").then(() => { |
| 76 | window.open(url, "_self"); | 77 | localStorage.removeItem('token') |
| 77 | sessionStorage.removeItem("navList"); | 78 | if (window._config.casEnable) { |
| 79 | window.location.href = window._config.casBaseURL + '/logout?service=' + encodeURIComponent(window.location.href); | ||
| 80 | } else { | ||
| 81 | this.$router.push({ | ||
| 82 | path: '/login', | ||
| 83 | replace: true, | ||
| 84 | query: { | ||
| 85 | redirect: router.currentRoute.value.fullPath | ||
| 86 | } | ||
| 87 | }) | ||
| 88 | } | ||
| 89 | }) | ||
| 78 | }, | 90 | }, |
| 79 | 91 | ||
| 80 | themeChange (val) { | 92 | themeChange (val) { | ... | ... |
| 1 | /* | 1 | /* |
| 2 | * @Description: 项目权限 | 2 | * @Description: 项目权限 |
| 3 | * @Autor: renchao | 3 | * @Autor: renchao |
| 4 | * @LastEditTime: 2023-05-16 14:10:26 | 4 | * @LastEditTime: 2023-05-31 15:55:14 |
| 5 | */ | 5 | */ |
| 6 | import Vue from 'vue' | 6 | import Vue from 'vue' |
| 7 | import router from './router' | 7 | import router from './router' |
| 8 | import store from './store' | 8 | import store from './store' |
| 9 | import axios from 'axios' | ||
| 9 | import { getMenuInfo } from '@/api/user' | 10 | import { getMenuInfo } from '@/api/user' |
| 11 | import { getUrlParam } from '@/utils/operation' | ||
| 10 | import NProgress from 'nprogress' // progress bar | 12 | import NProgress from 'nprogress' // progress bar |
| 11 | import 'nprogress/nprogress.css' // progress bar style | 13 | import 'nprogress/nprogress.css' // progress bar style |
| 12 | import getPageTitle from '@/utils/get-page-title' | 14 | import getPageTitle from '@/utils/get-page-title' |
| ... | @@ -19,24 +21,78 @@ router.beforeEach(async (to, from, next) => { | ... | @@ -19,24 +21,78 @@ router.beforeEach(async (to, from, next) => { |
| 19 | document.title = getPageTitle(to.meta.title) | 21 | document.title = getPageTitle(to.meta.title) |
| 20 | let hasAddDict = store.state.dict.addDict | 22 | let hasAddDict = store.state.dict.addDict |
| 21 | let hasAddRoute = store.state.permission.addRoutes | 23 | let hasAddRoute = store.state.permission.addRoutes |
| 22 | if (!hasAddDict) { | 24 | // cas操作 |
| 23 | store.dispatch('dict/generateDic') | 25 | const token = localStorage.getItem("token") |
| 26 | if (to.path === '/login') { | ||
| 27 | if (token) { | ||
| 28 | next('/') | ||
| 29 | } else { | ||
| 30 | next() | ||
| 31 | } | ||
| 32 | return | ||
| 24 | } | 33 | } |
| 25 | if (hasAddRoute) { | 34 | if (window._config.casEnable === true) { |
| 26 | next() | 35 | let locationUrl = window.location.protocol + '//' + window.location.host + window.location.pathname; |
| 27 | // next({ ...to, replace: true }) | 36 | if (!token) { |
| 28 | } else { | 37 | let ticket = getUrlParam('ticket'); |
| 29 | const { result: getMenuData } = await getMenuInfo() | 38 | if (ticket) { |
| 30 | const accessRoutes = await store.dispatch('permission/generateRoutes', getMenuData) | 39 | axios.get(Vue.prototype.BASE_API.ip + "/management/cas/validate", { |
| 31 | // 获取用户信息 | 40 | params: { |
| 32 | await store.dispatch('user/getUserInfo') | 41 | 'ticket': ticket, |
| 33 | router.addRoutes([...accessRoutes, { path: '*', redirect: '/404', hidden: true }]) | 42 | 'service': locationUrl |
| 34 | const routeTo = Cookies.get('routerTo') | 43 | } |
| 35 | if (routeTo && routeTo !== '/') { | 44 | }).then(async (res) => { |
| 36 | next({ ...to, replace: true }) | 45 | localStorage.setItem('token', res.data.content.accessToken) |
| 46 | window.location.href = localStorage.getItem('location') | ||
| 47 | |||
| 48 | }).catch(e => { | ||
| 49 | console.log(e) | ||
| 50 | }) | ||
| 51 | } else { | ||
| 52 | localStorage.setItem("location", window.location.href) | ||
| 53 | window.location.href = window._config.casBaseURL + '/login?service=' + encodeURIComponent(locationUrl); | ||
| 54 | permission() | ||
| 55 | } | ||
| 37 | } else { | 56 | } else { |
| 38 | next('/home') | 57 | permission() |
| 39 | } | 58 | } |
| 59 | async function permission () { | ||
| 60 | if (!hasAddDict) { | ||
| 61 | store.dispatch('dict/generateDic') | ||
| 62 | } | ||
| 63 | if (hasAddRoute) { | ||
| 64 | next() | ||
| 65 | // next({ ...to, replace: true }) | ||
| 66 | } else { | ||
| 67 | const { result: getMenuData } = await getMenuInfo() | ||
| 68 | const accessRoutes = await store.dispatch('permission/generateRoutes', getMenuData) | ||
| 69 | // 获取用户信息 | ||
| 70 | await store.dispatch('user/getUserInfo') | ||
| 71 | router.addRoutes([...accessRoutes, { path: '*', redirect: '/404', hidden: true }]) | ||
| 72 | const routeTo = Cookies.get('routerTo') | ||
| 73 | if (routeTo && routeTo !== '/') { | ||
| 74 | next({ ...to, replace: true }) | ||
| 75 | } else { | ||
| 76 | next('/home') | ||
| 77 | } | ||
| 78 | } | ||
| 79 | } | ||
| 80 | } else { | ||
| 81 | if (!token) { | ||
| 82 | const redirectData = { | ||
| 83 | path: '/login', | ||
| 84 | replace: true, | ||
| 85 | } | ||
| 86 | if (to.path) { | ||
| 87 | redirectData.query = { | ||
| 88 | ...redirectData.query, | ||
| 89 | redirect: to.path, | ||
| 90 | }; | ||
| 91 | } | ||
| 92 | next(redirectData) | ||
| 93 | return | ||
| 94 | } | ||
| 95 | next() | ||
| 40 | } | 96 | } |
| 41 | NProgress.done() | 97 | NProgress.done() |
| 42 | }) | 98 | }) | ... | ... |
| 1 | /* | 1 | /* |
| 2 | * @Description: 全局路由 | 2 | * @Description: 全局路由 |
| 3 | * @Autor: renchao | 3 | * @Autor: renchao |
| 4 | * @LastEditTime: 2023-05-16 14:09:37 | 4 | * @LastEditTime: 2023-05-26 17:11:19 |
| 5 | */ | 5 | */ |
| 6 | import Vue from 'vue' | 6 | import Vue from 'vue' |
| 7 | import Router from 'vue-router' | 7 | import Router from 'vue-router' | ... | ... |
| 1 | @import "~@/styles/mixin.scss"; | 1 | @import "~@/styles/mixin.scss"; |
| 2 | .dialogBox { | 2 | .dialogBox { |
| 3 | border-radius: 8px; | 3 | border-radius: 4px; |
| 4 | overflow: hidden; | 4 | overflow: hidden; |
| 5 | background: #FFFFFF; | 5 | background: #FFFFFF; |
| 6 | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.10); | 6 | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.10); |
| ... | @@ -8,15 +8,33 @@ | ... | @@ -8,15 +8,33 @@ |
| 8 | .dialog_title { | 8 | .dialog_title { |
| 9 | display: flex; | 9 | display: flex; |
| 10 | position: relative; | 10 | position: relative; |
| 11 | top: -2px; | 11 | top: -4px; |
| 12 | 12 | ||
| 13 | b { | 13 | b { |
| 14 | @include flex-center; | 14 | display: flex; |
| 15 | justify-content:left; | ||
| 16 | align-items: center; | ||
| 15 | flex: 1; | 17 | flex: 1; |
| 16 | width: 100%; | 18 | width: 100%; |
| 19 | margin-left: 10px; | ||
| 20 | width: 79px; | ||
| 21 | height: 12px; | ||
| 22 | font-size: 16px; | ||
| 23 | font-family: AlibabaPuHuiTi_2_65_Medium; | ||
| 24 | color: #31333C; | ||
| 25 | line-height: 10px; | ||
| 17 | } | 26 | } |
| 18 | } | 27 | } |
| 19 | 28 | .dialog_title::before{ | |
| 29 | content: ""; | ||
| 30 | display: block; | ||
| 31 | width: 4px; | ||
| 32 | height: 18px; | ||
| 33 | background: #2E74D8; | ||
| 34 | position: absolute; | ||
| 35 | top: -4px; | ||
| 36 | left: 0px; | ||
| 37 | } | ||
| 20 | .dialog_full { | 38 | .dialog_full { |
| 21 | position: absolute; | 39 | position: absolute; |
| 22 | top: 0; | 40 | top: 0; |
| ... | @@ -46,10 +64,7 @@ | ... | @@ -46,10 +64,7 @@ |
| 46 | } | 64 | } |
| 47 | 65 | ||
| 48 | .el-dialog__header { | 66 | .el-dialog__header { |
| 49 | margin-bottom: 10px; | 67 | background: linear-gradient(270deg, #F2F3FB 0%, #5C95E5 100%); |
| 50 | color: #FFFFFF; | ||
| 51 | background-color: #FCFDFD; | ||
| 52 | border-bottom: 1px solid #E4EBF4; | ||
| 53 | } | 68 | } |
| 54 | 69 | ||
| 55 | .el-dialog__body { | 70 | .el-dialog__body { |
| ... | @@ -87,4 +102,4 @@ | ... | @@ -87,4 +102,4 @@ |
| 87 | top: 50% !important; | 102 | top: 50% !important; |
| 88 | left: 50% !important; | 103 | left: 50% !important; |
| 89 | transform: translate(-50%, -50%) !important; | 104 | transform: translate(-50%, -50%) !important; |
| 90 | } | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 105 | } | ... | ... |
| ... | @@ -110,3 +110,26 @@ export function down (index, data) { | ... | @@ -110,3 +110,26 @@ export function down (index, data) { |
| 110 | data.splice(index, 0, downData); | 110 | data.splice(index, 0, downData); |
| 111 | } | 111 | } |
| 112 | } | 112 | } |
| 113 | |||
| 114 | |||
| 115 | export function getUrlParam (paraName) { | ||
| 116 | let url = document.location.toString(); | ||
| 117 | let arrObj = url.split('?'); | ||
| 118 | |||
| 119 | if (arrObj.length > 1) { | ||
| 120 | let arrPara = arrObj[1].split('&'); | ||
| 121 | let arr; | ||
| 122 | |||
| 123 | for (let i = 0; i < arrPara.length; i++) { | ||
| 124 | arr = arrPara[i].split('='); | ||
| 125 | |||
| 126 | if (arr != null && arr[0] === paraName) { | ||
| 127 | const index = arr[1].indexOf("#"); | ||
| 128 | return arr[1].substring(0, index); | ||
| 129 | } | ||
| 130 | } | ||
| 131 | return ''; | ||
| 132 | } else { | ||
| 133 | return ''; | ||
| 134 | } | ||
| 135 | } | ... | ... |
| 1 | /* | 1 | /* |
| 2 | * @Description: 此文件主要创建 axios 实例,然后添加请求拦截器和响应拦截器 | 2 | * @Description: 此文件主要创建 axios 实例,然后添加请求拦截器和响应拦截器 |
| 3 | * @Autor: renchao | 3 | * @Autor: renchao |
| 4 | * @LastEditTime: 2023-05-16 14:07:58 | 4 | * @LastEditTime: 2023-05-31 15:30:02 |
| 5 | */ | 5 | */ |
| 6 | import axios from 'axios' | 6 | import axios from 'axios' |
| 7 | import { Message } from 'element-ui' | 7 | import { Message } from 'element-ui' |
| ... | @@ -10,9 +10,9 @@ import { endLoadingSubCount } from './requestLoading' | ... | @@ -10,9 +10,9 @@ import { endLoadingSubCount } from './requestLoading' |
| 10 | // create an axios instance | 10 | // create an axios instance |
| 11 | const service = axios.create({ | 11 | const service = axios.create({ |
| 12 | baseURL: | 12 | baseURL: |
| 13 | process.env.NODE_ENV == "development" | 13 | process.env.NODE_ENV == "development" |
| 14 | ? process.env.VUE_APP_BASE_API | 14 | ? process.env.VUE_APP_BASE_API |
| 15 | : window.baseUrl + "/", | 15 | : window.baseUrl + "/", |
| 16 | withCredentials: true, //是否允许跨域 | 16 | withCredentials: true, //是否允许跨域 |
| 17 | headers: { | 17 | headers: { |
| 18 | 'Content-Type': 'application/json; charset=utf-8' | 18 | 'Content-Type': 'application/json; charset=utf-8' |
| ... | @@ -23,13 +23,14 @@ const service = axios.create({ | ... | @@ -23,13 +23,14 @@ const service = axios.create({ |
| 23 | // request interceptor | 23 | // request interceptor |
| 24 | service.interceptors.request.use( | 24 | service.interceptors.request.use( |
| 25 | config => { | 25 | config => { |
| 26 | // do something before request is sent | 26 | const token = localStorage.getItem('token') |
| 27 | if (process.env.NODE_ENV === "production") { | 27 | // 添加请求头 |
| 28 | return config; | 28 | if (token) { |
| 29 | config.headers['Authorization'] = "Bearer " + token | ||
| 29 | } else { | 30 | } else { |
| 30 | config.headers.Authorization = authorization; | 31 | config.headers.delete('Authorization') |
| 31 | return config; | ||
| 32 | } | 32 | } |
| 33 | return config; | ||
| 33 | }, | 34 | }, |
| 34 | error => { | 35 | error => { |
| 35 | // do something with request error | 36 | // do something with request error |
| ... | @@ -55,13 +56,35 @@ service.interceptors.response.use( | ... | @@ -55,13 +56,35 @@ service.interceptors.response.use( |
| 55 | }, | 56 | }, |
| 56 | error => { | 57 | error => { |
| 57 | endLoadingSubCount() | 58 | endLoadingSubCount() |
| 58 | // 对响应错误做点什么 | 59 | if (error.response.status === 401) { |
| 59 | Message({ | 60 | //todo: 需要解决 一个页面多个请求,刷新后此处会触发多次 |
| 60 | message: '服务器异常,请联系管理员', | 61 | if (window.__isNeedLogin) { |
| 61 | type: 'error', | 62 | window.__isNeedLogin = false |
| 62 | duration: 5 * 1000, | 63 | this.$message.error('token失效,请重新登录'); |
| 63 | customClass: 'messageIndex' | 64 | let locationUrl = window.location.protocol + '//' + window.location.host + window.location.pathname; |
| 64 | }) | 65 | localStorage.removeItem('token') |
| 66 | if (window._config.casEnable) { | ||
| 67 | window.location.href = window._config.casBaseURL + '/logout?service=' + encodeURIComponent(locationUrl); | ||
| 68 | } else { | ||
| 69 | router.replace({ | ||
| 70 | path: '/login', | ||
| 71 | query: { | ||
| 72 | redirect: router.currentRoute.value.fullPath | ||
| 73 | } | ||
| 74 | }) | ||
| 75 | return false | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | } else { | ||
| 80 | // 对响应错误做点什么 | ||
| 81 | Message({ | ||
| 82 | message: '服务器异常,请联系管理员', | ||
| 83 | type: 'error', | ||
| 84 | duration: 5 * 1000, | ||
| 85 | customClass: 'messageIndex' | ||
| 86 | }) | ||
| 87 | } | ||
| 65 | return Promise.reject(error); | 88 | return Promise.reject(error); |
| 66 | } | 89 | } |
| 67 | ) | 90 | ) | ... | ... |
-
Please register or sign in to post a comment