刘力
3 years ago
13 changed files with 535 additions and 386 deletions
-
5.editorconfig
-
2src/App.vue
-
101src/api/system/menu.js
-
117src/layout/index.vue
-
24src/main.js
-
168src/router/index.js
-
51src/router/routers.js
-
19src/store/index.js
-
36src/store/modules/api.js
-
148src/store/modules/permission.js
-
18src/utils/permission.js
-
202src/utils/request.js
-
24src/views/login.vue
@ -1,85 +1,82 @@ |
|||
import request from '@/utils/request' |
|||
|
|||
|
|||
import request from '@/utils/request'; |
|||
|
|||
//根据pid 获取菜单
|
|||
export function getMenusTree(pid) { |
|||
return request({ |
|||
url: 'api/menus/lazy?pid=' + pid, |
|||
method: 'get' |
|||
}) |
|||
return request({ |
|||
url: 'api/menus/lazy?pid=' + pid, |
|||
method: 'get' |
|||
}); |
|||
} |
|||
|
|||
export function getMenus(params) { |
|||
return request({ |
|||
url: 'api/menus', |
|||
method: 'get', |
|||
params |
|||
}) |
|||
return request({ |
|||
url: 'api/menus', |
|||
method: 'get', |
|||
params |
|||
}); |
|||
} |
|||
|
|||
//根据id获取上级菜单
|
|||
export function getMenuSuperior(ids) { |
|||
const data = ids.length || ids.length === 0 ? ids : Array.of(ids) |
|||
return request({ |
|||
url: 'api/menus/superior', |
|||
method: 'post', |
|||
data |
|||
}) |
|||
const data = ids.length || ids.length === 0 ? ids : Array.of(ids); |
|||
return request({ |
|||
url: 'api/menus/superior', |
|||
method: 'post', |
|||
data |
|||
}); |
|||
} |
|||
|
|||
//获取子菜单
|
|||
export function getChild(id) { |
|||
return request({ |
|||
url: 'api/menus/child?id=' + id, |
|||
method: 'get' |
|||
}) |
|||
return request({ |
|||
url: 'api/menus/child?id=' + id, |
|||
method: 'get' |
|||
}); |
|||
} |
|||
|
|||
//构建菜单
|
|||
export function bulidMenus() { |
|||
return request({ |
|||
url: 'api/menus', |
|||
method: 'post', |
|||
data |
|||
}) |
|||
return request({ |
|||
url: 'api/menus', |
|||
method: 'post', |
|||
data |
|||
}); |
|||
} |
|||
|
|||
//新增菜单
|
|||
export function add(data) { |
|||
return request({ |
|||
url: 'api/menus', |
|||
method: 'post', |
|||
data |
|||
}) |
|||
return request({ |
|||
url: 'api/menus', |
|||
method: 'post', |
|||
data |
|||
}); |
|||
} |
|||
|
|||
//删除菜单
|
|||
export function del(ids) { |
|||
return request({ |
|||
url: 'api/menus', |
|||
method: 'delete', |
|||
data: ids |
|||
}) |
|||
return request({ |
|||
url: 'api/menus', |
|||
method: 'delete', |
|||
data: ids |
|||
}); |
|||
} |
|||
|
|||
//修改菜单
|
|||
export function edit(data) { |
|||
return request({ |
|||
url: 'api/menus', |
|||
method: 'put', |
|||
data |
|||
}) |
|||
return request({ |
|||
url: 'api/menus', |
|||
method: 'put', |
|||
data |
|||
}); |
|||
} |
|||
|
|||
|
|||
export default { |
|||
add, |
|||
edit, |
|||
del, |
|||
getMenus, |
|||
getMenusTree, |
|||
getMenuSuperior, |
|||
getChild, |
|||
getMenusTree |
|||
} |
|||
add, |
|||
edit, |
|||
del, |
|||
getMenus, |
|||
getMenusTree, |
|||
getMenuSuperior, |
|||
getChild, |
|||
getMenusTree |
|||
}; |
@ -0,0 +1,117 @@ |
|||
<template> |
|||
<div :class="classObj" class="app-wrapper"> |
|||
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside" /> |
|||
<sidebar class="sidebar-container" /> |
|||
<div :class="{hasTagsView:needTagsView}" class="main-container"> |
|||
<div :class="{'fixed-header':fixedHeader}"> |
|||
<navbar /> |
|||
<tags-view v-if="needTagsView" /> |
|||
</div> |
|||
<app-main /> |
|||
<right-panel v-if="showSettings"> |
|||
<settings /> |
|||
</right-panel> |
|||
</div> |
|||
<!-- 防止刷新后主题丢失 --> |
|||
<Theme v-show="false" ref="theme" /> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import RightPanel from '@/components/RightPanel' |
|||
import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components' |
|||
import ResizeMixin from './mixin/ResizeHandler' |
|||
import { mapState } from 'vuex' |
|||
import Theme from '@/components/ThemePicker' |
|||
import Cookies from 'js-cookie' |
|||
export default { |
|||
name: 'Layout', |
|||
components: { |
|||
AppMain, |
|||
Navbar, |
|||
RightPanel, |
|||
Settings, |
|||
Sidebar, |
|||
TagsView, |
|||
Theme |
|||
|
|||
}, |
|||
mixins: [ResizeMixin], |
|||
computed: { |
|||
...mapState({ |
|||
sidebar: state => state.app.sidebar, |
|||
device: state => state.app.device, |
|||
showSettings: state => state.settings.showSettings, |
|||
needTagsView: state => state.settings.tagsView, |
|||
fixedHeader: state => state.settings.fixedHeader |
|||
}), |
|||
classObj () { |
|||
return { |
|||
hideSidebar: !this.sidebar.opened, |
|||
openSidebar: this.sidebar.opened, |
|||
withoutAnimation: this.sidebar.withoutAnimation, |
|||
mobile: this.device === 'mobile' |
|||
} |
|||
} |
|||
}, |
|||
mounted () { |
|||
if (Cookies.get('theme')) { |
|||
this.$refs.theme.theme = Cookies.get('theme') |
|||
this.$store.dispatch('settings/changeSetting', { |
|||
key: 'theme', |
|||
value: Cookies.get('theme') |
|||
}) |
|||
} |
|||
}, |
|||
methods: { |
|||
handleClickOutside () { |
|||
this.$store.dispatch('app/closeSideBar', { withoutAnimation: false }) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
@import '~@/assets/styles/mixin.scss'; |
|||
@import '~@/assets/styles/variables.scss'; |
|||
|
|||
.app-wrapper { |
|||
@include clearfix; |
|||
position: relative; |
|||
height: 100%; |
|||
width: 100%; |
|||
|
|||
&.mobile.openSidebar { |
|||
position: fixed; |
|||
top: 0; |
|||
} |
|||
} |
|||
|
|||
.drawer-bg { |
|||
background: #000; |
|||
opacity: 0.3; |
|||
width: 100%; |
|||
top: 0; |
|||
height: 100%; |
|||
position: absolute; |
|||
z-index: 999; |
|||
} |
|||
|
|||
.fixed-header { |
|||
position: fixed; |
|||
top: 0; |
|||
right: 0; |
|||
z-index: 9; |
|||
width: calc(100% - #{$sideBarWidth}); |
|||
transition: width 0.28s; |
|||
padding: 0; |
|||
} |
|||
|
|||
.hideSidebar .fixed-header { |
|||
width: calc(100% - 54px); |
|||
} |
|||
|
|||
.mobile .fixed-header { |
|||
width: 100%; |
|||
} |
|||
</style> |
@ -1,28 +1,28 @@ |
|||
//适配Nginx反向代理
|
|||
const baseUrl = process.env.VUE_APP_BASE_API === '/' ? '' : process.env.VUE_APP_BASE_API |
|||
const baseUrl = |
|||
process.env.VUE_APP_BASE_API === '/' ? '' : process.env.VUE_APP_BASE_API; |
|||
|
|||
//适配API路径
|
|||
const api = { |
|||
state: { |
|||
state: { |
|||
//部署包上传
|
|||
//deployUploadApi: baseUrl + '/api/deploy/upload',
|
|||
|
|||
//部署包上传
|
|||
//deployUploadApi: baseUrl + '/api/deploy/upload',
|
|||
//图片上传
|
|||
imagesUplaodApi: baseUrl + '/api/localStorage/pictures', |
|||
|
|||
//图片上传
|
|||
imagesUplaodApi: baseUrl + '/api/localStorage/pictures', |
|||
//上传图像
|
|||
updateAvatarApi: baseUrl + '/api/users/updateAvatar', |
|||
|
|||
//上传图像
|
|||
updateAvatarApi: baseUrl + '/api/users/updateAvatar', |
|||
//文件上传
|
|||
fileUploadApi: baseUrl + '/api/localStorage', |
|||
|
|||
//文件上传
|
|||
fileUploadApi: baseUrl + '/api/localStorage', |
|||
// swagger
|
|||
swaggerApi: baseUrl + '/swagger-ui.html', |
|||
|
|||
// swagger
|
|||
swaggerApi: baseUrl + '/swagger-ui.html', |
|||
//基础url
|
|||
baseApi: baseUrl |
|||
} |
|||
}; |
|||
|
|||
//基础url
|
|||
baseApi: baseUrl |
|||
} |
|||
} |
|||
|
|||
export default api |
|||
export default api; |
@ -1,86 +1,88 @@ |
|||
import { constantRouterMap } from "@/router/routers"; |
|||
import Layout from '@/layout/index' |
|||
import ParentView from '@/components/ParentView' |
|||
import { constantRouterMap } from '@/router/routers'; |
|||
import Layout from '@/layout/index'; |
|||
import ParentView from '@/components/ParentView'; |
|||
|
|||
const permission = { |
|||
//存放状态
|
|||
state: { |
|||
routers: constantRouterMap, |
|||
addRouters: [], |
|||
sidebarRouters: [] |
|||
}, |
|||
//同步更改状态
|
|||
mutations: { |
|||
SET_ROUTERS: (state, routers) => { |
|||
state.addRouters = routers |
|||
state.routers = constantRouterMap.concat(routers) |
|||
//存放状态
|
|||
state: { |
|||
routers: constantRouterMap, |
|||
addRouters: [], |
|||
sidebarRouters: [] |
|||
}, |
|||
SET_SIDEBAR_ROUTERS: (state, routers) => { |
|||
state.sidebarRouters = constantRouterMap.concat(routers) |
|||
} |
|||
}, |
|||
//发送异步请求拿到数据
|
|||
actions: { |
|||
GenerateRoutes({ |
|||
commit |
|||
}, asyncRouter) { |
|||
commit('SET_ROUTERS', asyncRouter) |
|||
//同步更改状态
|
|||
mutations: { |
|||
SET_ROUTERS: (state, routers) => { |
|||
state.addRouters = routers; |
|||
state.routers = constantRouterMap.concat(routers); |
|||
}, |
|||
SET_SIDEBAR_ROUTERS: (state, routers) => { |
|||
state.sidebarRouters = constantRouterMap.concat(routers); |
|||
} |
|||
}, |
|||
SetSidebarRouters({ |
|||
commit |
|||
}, sidebarRouter) { |
|||
commit('SET_SIDEBAR_ROUTERS', sidebarRouter) |
|||
//发送异步请求拿到数据
|
|||
actions: { |
|||
GenerateRoutes({ commit }, asyncRouter) { |
|||
commit('SET_ROUTERS', asyncRouter); |
|||
}, |
|||
SetSidebarRouters({ commit }, sidebarRouter) { |
|||
commit('SET_SIDEBAR_ROUTERS', sidebarRouter); |
|||
} |
|||
} |
|||
} |
|||
|
|||
} |
|||
}; |
|||
|
|||
//遍历后台传来的路由字符串,转换为组件对象
|
|||
export const filterAsyncRouter = (routers, isRewrite = false) => { |
|||
return routers.filter(router => { |
|||
if (isRewrite && router.children) { |
|||
router.children = filterChildren(router.children) |
|||
} |
|||
if (router.component) { |
|||
if (router.component === 'Layout') { // Layout组件特殊处理
|
|||
router.component = Layout |
|||
} else if (router.component === 'ParentView') { |
|||
router.component = ParentView |
|||
} else { |
|||
const component = router.component |
|||
router.component = loadView(component) |
|||
} |
|||
} |
|||
if (router.children && router.children.length) { |
|||
router.children = filterAsyncRouter(router.children, router, isRewrite) |
|||
} |
|||
return true |
|||
}) |
|||
} |
|||
return routers.filter(router => { |
|||
if (isRewrite && router.children) { |
|||
router.children = filterChildren(router.children); |
|||
} |
|||
if (router.component) { |
|||
if (router.component === 'Layout') { |
|||
// Layout组件特殊处理
|
|||
router.component = Layout; |
|||
} else if (router.component === 'ParentView') { |
|||
router.component = ParentView; |
|||
} else { |
|||
const component = router.component; |
|||
router.component = loadView(component); |
|||
} |
|||
} |
|||
if (router.children && router.children.length) { |
|||
router.children = filterAsyncRouter( |
|||
router.children, |
|||
router, |
|||
isRewrite |
|||
); |
|||
} |
|||
return true; |
|||
}); |
|||
}; |
|||
|
|||
function filterChildren(childrenMap) { |
|||
var children = [] |
|||
childrenMap.forEach((el, index) => { |
|||
if (el.children && el.children.length) { |
|||
if (el.component === 'ParentView') { |
|||
el.children.forEach(c => { |
|||
c.path = el.path + '/' + c.path |
|||
if (c.children && c.children.length) { |
|||
children = children.concat(filterChildren(c.children, c)) |
|||
return |
|||
} |
|||
children.push(c) |
|||
}) |
|||
return |
|||
} |
|||
} |
|||
children = children.concat(el) |
|||
}) |
|||
return children |
|||
var children = []; |
|||
childrenMap.forEach((el, index) => { |
|||
if (el.children && el.children.length) { |
|||
if (el.component === 'ParentView') { |
|||
el.children.forEach(c => { |
|||
c.path = el.path + '/' + c.path; |
|||
if (c.children && c.children.length) { |
|||
children = children.concat( |
|||
filterChildren(c.children, c) |
|||
); |
|||
return; |
|||
} |
|||
children.push(c); |
|||
}); |
|||
return; |
|||
} |
|||
} |
|||
children = children.concat(el); |
|||
}); |
|||
return children; |
|||
} |
|||
|
|||
export const loadView = (view) => { |
|||
return (resolve) => require([`@/views/${view}`], resolve) |
|||
} |
|||
export const loadView = view => { |
|||
return resolve => require([`@/views/${view}`], resolve); |
|||
}; |
|||
|
|||
export default permission |
|||
export default permission; |
@ -1,121 +1,125 @@ |
|||
import axios from "axios" |
|||
import axios from 'axios' |
|||
import router from '@/router/routers' |
|||
import { Notification } from 'element-ui' //elementUI 提示框组件
|
|||
import { Notification } from 'element-ui' //elementUI 提示框组件
|
|||
import store from '../store' |
|||
import { getToken } from '@/utils/auth' |
|||
import Config from '@/settings' |
|||
import Cookies from "js-cookie" |
|||
|
|||
import Cookies from 'js-cookie' |
|||
|
|||
//二次封装axios,创建axios 实例
|
|||
const service = axios.create({ |
|||
//api 的 base_url在.env.development有配置
|
|||
baseURL: process.env.NODE_ENV === 'production' ? process.env.VUE_APP_BASE_API : '/', |
|||
//请求超时时间
|
|||
timeout: Config.timeout |
|||
//api 的 base_url在.env.development有配置
|
|||
baseURL: |
|||
process.env.NODE_ENV === 'production' |
|||
? process.env.VUE_APP_BASE_API |
|||
: '/', |
|||
//请求超时时间
|
|||
timeout: Config.timeout |
|||
}) |
|||
|
|||
|
|||
//添加请求拦截器
|
|||
service.interceptors.request.use( |
|||
// 在发送请求之前做些什么
|
|||
config => { |
|||
//如果获取token
|
|||
if (getToken()) { |
|||
//每次请求都附带上header的Authorization
|
|||
config.headers['Authorization'] = getToken() |
|||
// 在发送请求之前做些什么
|
|||
config => { |
|||
//如果获取token
|
|||
if (getToken()) { |
|||
//每次请求都附带上header的Authorization
|
|||
config.headers['Authorization'] = getToken() |
|||
} |
|||
//请求格式
|
|||
config.headers['Content-Type'] = 'application/json' |
|||
return config |
|||
}, |
|||
error => { |
|||
//对请求错误的处理
|
|||
Promise.reject(error) |
|||
} |
|||
//请求格式
|
|||
config.headers['Content-Type'] = 'application/json' |
|||
return config |
|||
}, |
|||
error => { |
|||
//对请求错误的处理
|
|||
Promise.reject(error) |
|||
} |
|||
) |
|||
|
|||
//添加响应拦截器
|
|||
service.interceptors.response.use( |
|||
//响应后要做的事情
|
|||
response => { |
|||
//返回响应数据
|
|||
return response.data |
|||
}, |
|||
//响应错误处理
|
|||
error => { |
|||
//兼容blob下载出错json提示
|
|||
if (error.response.data instanceof Blob && error.response.data.type.toLowerCase().indexOf('json') !== -1) { |
|||
//创建文件读取对象
|
|||
const reader = new FileReader() |
|||
//读取指定的Blob中错误信息内容
|
|||
reader.readAsText(error.response.data, 'utf-8') |
|||
//读取文件完成后触发onload事件
|
|||
reader.onload = function (e) { |
|||
//转换错误信息
|
|||
const errorMsg = JSON.parse(reader.result).message |
|||
//通知提醒框返回错误信息
|
|||
Notification.error({ |
|||
title: errorMsg, |
|||
duration: 5000 |
|||
}) |
|||
} |
|||
} else { |
|||
let code = 0 |
|||
//捕获错误信息
|
|||
try { |
|||
//获取响应错误状态码
|
|||
code = error.response.data.status |
|||
} catch (e) { |
|||
//做请求超时判断
|
|||
if (error.toString().indexOf('Error:timeout') !== -1) { |
|||
Notification.error({ |
|||
title: '网络请求超时', |
|||
duration: 5000 |
|||
}) |
|||
//拿到回调信息并返回
|
|||
return Promise.reject(error) |
|||
} |
|||
} |
|||
console.log(code) |
|||
//错误代码判断
|
|||
if (code) { |
|||
if (code === 401) { |
|||
//跳转401并写入Cookies
|
|||
store.dispatch('LogOut').then(() => { |
|||
// 用户登录界面提示
|
|||
Cookies.set('point', 401) |
|||
//重新加载
|
|||
location.reload() |
|||
}) |
|||
} else if (code === 403) { |
|||
//如果是403直接返回401页面路径
|
|||
router.push({ |
|||
path: '/401' |
|||
}) |
|||
//响应后要做的事情
|
|||
response => { |
|||
//返回响应数据
|
|||
return response.data |
|||
}, |
|||
//响应错误处理
|
|||
error => { |
|||
//兼容blob下载出错json提示
|
|||
if ( |
|||
error.response.data instanceof Blob && |
|||
error.response.data.type.toLowerCase().indexOf('json') !== -1 |
|||
) { |
|||
//创建文件读取对象
|
|||
const reader = new FileReader() |
|||
//读取指定的Blob中错误信息内容
|
|||
reader.readAsText(error.response.data, 'utf-8') |
|||
//读取文件完成后触发onload事件
|
|||
reader.onload = function(e) { |
|||
//转换错误信息
|
|||
const errorMsg = JSON.parse(reader.result).message |
|||
//通知提醒框返回错误信息
|
|||
Notification.error({ |
|||
title: errorMsg, |
|||
duration: 5000 |
|||
}) |
|||
} |
|||
} else { |
|||
//获取错误信息
|
|||
const errorMsg = error.response.data.message |
|||
if (errorMsg !== undefined) { |
|||
//告知提示框错误信息
|
|||
Notification.error({ |
|||
title: errorMsg, |
|||
duration: 5000 |
|||
}) |
|||
} |
|||
let code = 0 |
|||
//捕获错误信息
|
|||
try { |
|||
//获取响应错误状态码
|
|||
code = error.response.data.status |
|||
} catch (e) { |
|||
//做请求超时判断
|
|||
if (error.toString().indexOf('Error:timeout') !== -1) { |
|||
Notification.error({ |
|||
title: '网络请求超时', |
|||
duration: 5000 |
|||
}) |
|||
//拿到回调信息并返回
|
|||
return Promise.reject(error) |
|||
} |
|||
} |
|||
console.log(code) |
|||
//错误代码判断
|
|||
if (code) { |
|||
if (code === 401) { |
|||
//跳转401并写入Cookies
|
|||
store.dispatch('LogOut').then(() => { |
|||
// 用户登录界面提示
|
|||
Cookies.set('point', 401) |
|||
//重新加载
|
|||
location.reload() |
|||
}) |
|||
} else if (code === 403) { |
|||
//如果是403直接返回401页面路径
|
|||
router.push({ |
|||
path: '/401' |
|||
}) |
|||
} else { |
|||
//获取错误信息
|
|||
const errorMsg = error.response.data.message |
|||
if (errorMsg !== undefined) { |
|||
//告知提示框错误信息
|
|||
Notification.error({ |
|||
title: errorMsg, |
|||
duration: 5000 |
|||
}) |
|||
} |
|||
} |
|||
} else { |
|||
//否则把请求接口失败告知提示框
|
|||
Notification.error({ |
|||
title: '接口请求失败', |
|||
duration: 5000 |
|||
}) |
|||
} |
|||
} |
|||
} else { |
|||
//否则把请求接口失败告知提示框
|
|||
Notification.error({ |
|||
title: '接口请求失败', |
|||
duration: 5000 |
|||
}) |
|||
} |
|||
} |
|||
|
|||
//返回错误
|
|||
return Promise.reject(error) |
|||
} |
|||
//返回错误
|
|||
return Promise.reject(error) |
|||
} |
|||
) |
|||
|
|||
export default service |
Write
Preview
Loading…
Cancel
Save
Reference in new issue