持续修整内容

This commit is contained in:
zxx 2022-10-14 14:39:39 +08:00
parent d19ce89143
commit b5bf802ab2
23 changed files with 356 additions and 176 deletions

5
.env
View File

@ -2,8 +2,11 @@ VUE_APP_PUBLIC_PATH=/
VUE_APP_NAME=Admin VUE_APP_NAME=Admin
VUE_APP_ROUTES_KEY=admin.routes VUE_APP_ROUTES_KEY=admin.routes
VUE_APP_PERMISSIONS_KEY=admin.permissions VUE_APP_PERMISSIONS_KEY=admin.permissions
VUE_APP_UID_KEY=admin.uid
VUE_APP_USER_KEY=admin.user VUE_APP_USER_KEY=admin.user
VUE_APP_SETTING_KEY=admin.setting VUE_APP_SETTING_KEY=admin.setting
VUE_APP_USER_SETTINGS_KEY=admin.user.settings
VUE_APP_TBAS_KEY=admin.tabs VUE_APP_TBAS_KEY=admin.tabs
VUE_APP_TBAS_TITLES_KEY=admin.tabs.titles VUE_APP_TBAS_TITLES_KEY=admin.tabs.titles
VUE_APP_API_BASE_URL=http://192.168.31.91:19000 # VUE_APP_API_BASE_URL=http://192.168.31.91:19000
VUE_APP_API_BASE_URL=http://192.168.52.166:30000

View File

@ -1 +1,2 @@
VUE_APP_API_BASE_URL=http://192.168.31.91:19000
VUE_APP_API_BASE_URL=http://192.168.52.166:30000

View File

@ -1,19 +1,27 @@
<template> <template>
<a-layout :class="['admin-layout', 'beauty-scroll']"> <a-layout :class="['admin-layout', 'beauty-scroll']">
<drawer v-if="isMobile" v-model="drawerOpen"> <drawer v-if="isMobile" v-model="drawerOpen">
<side-menu :theme="theme.mode" :menuData="menuData" :collapsed="false" :collapsible="false" @menuSelect="onMenuSelect"/> <side-menu :theme="theme.mode" :menuData="menuData" :collapsed="false" :collapsible="false"
@menuSelect="onMenuSelect" />
</drawer> </drawer>
<side-menu :class="[fixedSideBar ? 'fixed-side' : '']" :theme="theme.mode" v-else-if="layout === 'side' || layout === 'mix'" :menuData="sideMenuData" :collapsed="collapsed" :collapsible="true" /> <side-menu :class="[fixedSideBar ? 'fixed-side' : '']" :theme="theme.mode"
<div v-if="fixedSideBar && !isMobile" :style="`width: ${sideMenuWidth}; min-width: ${sideMenuWidth};max-width: ${sideMenuWidth};`" class="virtual-side"></div> v-else-if="layout === 'side' || layout === 'mix'" :menuData="sideMenuData" :collapsed="collapsed"
:collapsible="true" />
<div v-if="fixedSideBar && !isMobile"
:style="`width: ${sideMenuWidth}; min-width: ${sideMenuWidth};max-width: ${sideMenuWidth};`" class="virtual-side">
</div>
<drawer v-if="!hideSetting" v-model="showSetting" placement="right"> <drawer v-if="!hideSetting" v-model="showSetting" placement="right">
<div class="setting" slot="handler"> <div class="setting" slot="handler">
<a-icon :type="showSetting ? 'close' : 'setting'"/> <a-icon :type="showSetting ? 'close' : 'setting'" />
</div> </div>
<setting /> <setting />
</drawer> </drawer>
<a-layout class="admin-layout-main beauty-scroll"> <a-layout class="admin-layout-main beauty-scroll">
<admin-header :class="[{'fixed-tabs': fixedTabs, 'fixed-header': fixedHeader, 'multi-page': multiPage}]" :style="headerStyle" :menuData="headMenuData" :collapsed="collapsed" @toggleCollapse="toggleCollapse"/> <admin-header :class="[{'fixed-tabs': fixedTabs, 'fixed-header': fixedHeader, 'multi-page': multiPage}]"
<a-layout-header :class="['virtual-header', {'fixed-tabs' : fixedTabs, 'fixed-header': fixedHeader, 'multi-page': multiPage}]" v-show="fixedHeader"></a-layout-header> :style="headerStyle" :menuData="headMenuData" :collapsed="collapsed" @toggleCollapse="toggleCollapse" />
<a-layout-header
:class="['virtual-header', {'fixed-tabs' : fixedTabs, 'fixed-header': fixedHeader, 'multi-page': multiPage}]"
v-show="fixedHeader"></a-layout-header>
<a-layout-content class="admin-layout-content" :style="`min-height: ${minHeight}px;`"> <a-layout-content class="admin-layout-content" :style="`min-height: ${minHeight}px;`">
<div style="position: relative"> <div style="position: relative">
<slot></slot> <slot></slot>
@ -32,17 +40,15 @@ import PageFooter from './footer/PageFooter' // 加载页脚组件
import Drawer from '../components/tool/Drawer' // import Drawer from '../components/tool/Drawer' //
import SideMenu from '../components/menu/SideMenu' // import SideMenu from '../components/menu/SideMenu' //
import Setting from '../components/setting/Setting' // import Setting from '../components/setting/Setting' //
import {mapState, mapMutations, mapGetters} from 'vuex' // vuex import { mapState, mapMutations, mapGetters } from 'vuex' // vuex
// const minHeight = window.innerHeight - 64 - 122 // const minHeight = window.innerHeight - 64 - 122
export default { export default {
name: 'AdminLayout', // name: 'AdminLayout', //
components: {Setting, SideMenu, Drawer, PageFooter, AdminHeader}, // components: { Setting, SideMenu, Drawer, PageFooter, AdminHeader }, //
data () { data() {
return { return {
minHeight: window.innerHeight - 64 - 122, // minHeight: window.innerHeight - 64 - 122, //
collapsed: false, // collapsed: false, //
@ -63,17 +69,17 @@ export default {
this.setActivated(this.$route) // this.setActivated(this.$route) //
}, },
isMobile(val) { // isMobile(val) { //
if(!val) { if (!val) {
this.drawerOpen = false this.drawerOpen = false
} }
} }
}, },
computed: { computed: {
...mapState('setting', ['isMobile', 'theme', 'layout', 'footerLinks', 'copyright', 'fixedHeader', 'fixedSideBar', ...mapState('setting', ['isMobile', 'theme', 'layout', 'footerLinks', 'copyright', 'fixedHeader', 'fixedSideBar',
'fixedTabs', 'hideSetting', 'multiPage']), 'fixedTabs', 'hideSetting', 'multiPage']),
// vuex // vuex
...mapGetters('setting', ['firstMenu', 'subMenu', 'menuData']), ...mapGetters('setting', ['firstMenu', 'subMenu', 'menuData']),
// vuex // vuex
sideMenuWidth() { // sideMenuWidth() { //
return this.collapsed ? '80px' : '256px' return this.collapsed ? '80px' : '256px'
}, },
@ -83,27 +89,27 @@ export default {
return `width: ${width}; position: ${position};` // return `width: ${width}; position: ${position};` //
}, },
headMenuData() { // headMenuData() { //
const {layout, menuData, firstMenu} = this // const { layout, menuData, firstMenu } = this //
return layout === 'mix' ? firstMenu : menuData // return layout === 'mix' ? firstMenu : menuData //
}, },
sideMenuData() { // sideMenuData() { //
const {layout, menuData, subMenu} = this // const { layout, menuData, subMenu } = this //
return layout === 'mix' ? subMenu : menuData // return layout === 'mix' ? subMenu : menuData //
} }
}, },
methods: { methods: {
...mapMutations('setting', ['correctPageMinHeight', 'setActivatedFirst']), // ...mapMutations('setting', ['correctPageMinHeight', 'setActivatedFirst']), //
toggleCollapse () { // toggleCollapse() { //
this.collapsed = !this.collapsed // this.collapsed = !this.collapsed //
}, },
onMenuSelect () { // onMenuSelect() { //
this.toggleCollapse() // this.toggleCollapse() //
}, },
setActivated(route) { // setActivated(route) { //
if (this.layout === 'mix') { // if (this.layout === 'mix') { //
let matched = route.matched // let matched = route.matched //
matched = matched.slice(0, matched.length - 1) // matched = matched.slice(0, matched.length - 1) //
const {firstMenu} = this // const { firstMenu } = this //
for (let menu of firstMenu) { // for (let menu of firstMenu) { //
if (matched.findIndex(item => item.path === menu.fullPath) !== -1) { // if (matched.findIndex(item => item.path === menu.fullPath) !== -1) { //
this.setActivatedFirst(menu.fullPath) // this.setActivatedFirst(menu.fullPath) //
@ -116,6 +122,7 @@ export default {
created() { // created() { //
this.correctPageMinHeight(this.minHeight - 24) // this.correctPageMinHeight(this.minHeight - 24) //
this.setActivated(this.$route) // this.setActivated(this.$route) //
}, },
beforeDestroy() { // beforeDestroy() { //
this.correctPageMinHeight(-this.minHeight + 24) // this.correctPageMinHeight(-this.minHeight + 24) //
@ -124,50 +131,57 @@ export default {
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.admin-layout{ .admin-layout {
.side-menu{ .side-menu {
&.fixed-side{ &.fixed-side {
position: fixed; position: fixed;
height: 100vh; height: 100vh;
left: 0; left: 0;
top: 0; top: 0;
}
} }
.virtual-side{ }
transition: all 0.2s;
.virtual-side {
transition: all 0.2s;
}
.virtual-header {
transition: all 0.2s;
opacity: 0;
&.fixed-tabs.multi-page:not(.fixed-header) {
height: 0;
} }
.virtual-header{ }
.admin-layout-main {
.admin-header {
top: 0;
right: 0;
overflow: hidden;
transition: all 0.2s; transition: all 0.2s;
opacity: 0;
&.fixed-tabs.multi-page:not(.fixed-header){ &.fixed-tabs.multi-page:not(.fixed-header) {
height: 0; height: 0;
} }
} }
.admin-layout-main{
.admin-header{
top: 0;
right: 0;
overflow: hidden;
transition: all 0.2s;
&.fixed-tabs.multi-page:not(.fixed-header){
height: 0;
}
}
}
.admin-layout-content{
padding: 24px 24px 0;
/*overflow-x: hidden;*/
/*min-height: calc(100vh - 64px - 122px);*/
}
.setting{
background-color: @primary-color;
color: @base-bg-color;
border-radius: 5px 0 0 5px;
line-height: 40px;
font-size: 22px;
width: 40px;
height: 40px;
box-shadow: -2px 0 8px @shadow-color;
}
} }
.admin-layout-content {
padding: 24px 24px 0;
/*overflow-x: hidden;*/
/*min-height: calc(100vh - 64px - 122px);*/
}
.setting {
background-color: @primary-color;
color: @base-bg-color;
border-radius: 5px 0 0 5px;
line-height: 40px;
font-size: 22px;
width: 40px;
height: 40px;
box-shadow: -2px 0 8px @shadow-color;
}
}
</style> </style>

View File

@ -86,6 +86,8 @@ export default {
marginCorrect() { // marginCorrect() { //
return this.multiPage ? 24 : 0 // return this.multiPage ? 24 : 0 //
} }
}, },
methods: { methods: {
...mapMutations('setting', ['correctPageMinHeight']), // vuex ...mapMutations('setting', ['correctPageMinHeight']), // vuex

View File

@ -14,6 +14,7 @@ import PageLayout from './PageLayout'
import PageToggleTransition from '../components/transition/PageToggleTransition'; import PageToggleTransition from '../components/transition/PageToggleTransition';
import {mapState} from 'vuex' import {mapState} from 'vuex'
export default { export default {
name: 'PageView', name: 'PageView',
components: {PageToggleTransition, PageLayout}, components: {PageToggleTransition, PageLayout},

View File

@ -82,10 +82,15 @@
<script> <script>
import CommonLayout from '@/layouts/CommonLayout' import CommonLayout from '@/layouts/CommonLayout'
import {login, getRoutesConfig} from '@/services/base/user' import {login,getUserInfo, getRoutesConfig,getPermission,getSettings} from '@/services/base/user'
import {setAuthorization} from '@/utils/request' import {setAuthorization} from '@/utils/request'
import {loadRoutes} from '@/utils/routerUtil' import {loadRoutes} from '@/utils/routerUtil'
import {mapMutations} from 'vuex' import {mapMutations} from 'vuex'
// import axios from 'axios' // import axios from 'axios'
export default { export default {
name: 'Login', name: 'Login',
@ -119,30 +124,10 @@ export default {
}, 1000) }, 1000)
}) // loadshpick }) // loadshpick
// // axios.post("http://192.168.52.166:30000/AdminUser/v1/login")
// axios.post("http://192.168.31.91:19000/AdminUser/v1/login",{
// // "mobile": "18678390480",
// // "password": "888888"
// },
// {
// // withCredentials: false
// })
// axios.post("http://192.168.31.91:19000/AdminUser/v1/routers",{
// //
// withCredentials: false,
// headers: {
// 'Content-Type': 'application/x-www-form-urlencoded',
// 'Access-Control-Allow-Origin': '*',
// 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
// }
// })
}, },
methods: { methods: {
...mapMutations('account', ['setUser']), ...mapMutations('account', ['setUid','setUser','setPermissions','setRoutesConfig','setSettings']),
onSubmit (e) { onSubmit (e) {
e.preventDefault() e.preventDefault()
@ -160,23 +145,39 @@ export default {
this.logging = false this.logging = false
const loginRes = res.data const loginRes = res.data
if (loginRes.code == 200) { if (loginRes.code == 200) {
const user = loginRes.data.uid const uid = loginRes.data.uid
console.log("user",user)
console.log("loginRes.data.access_expire",loginRes.data.access_expire) setAuthorization({token: loginRes.data.access_token, expireAt: new Date(loginRes.data.access_expire*1000)}) // token
console.log("loginRes.data.access_token",loginRes.data.access_token) this.setUid(uid) // id
this.setUser(user)
// this.setPermissions(permissions)
setAuthorization({token: loginRes.data.access_token, expireAt: new Date(loginRes.data.access_expire*1000)}) getUserInfo().then(result =>{ //
// console.log("UserInforesult:",result)
getRoutesConfig().then(result => { const UserInfo = result.data.data.user_info
console.log("UserInfo",UserInfo)
this.setUser(UserInfo)
})
getPermission().then(result => { //
const Permission = result.data.data.permission
console.log("Permissionresult:",result)
this.setPermissions(Permission)
})
getRoutesConfig().then(result => { //
const routesConfig = result.data.data const routesConfig = result.data.data
console.log("获取路由配置",[routesConfig]) this.setRoutesConfig(routesConfig)
loadRoutes([routesConfig]) loadRoutes([routesConfig])
console.log("开始跳转")
this.$router.push('/dashboard/workplace') this.$router.push('/dashboard/workplace')
console.log("跳转结束")
this.$message.success(loginRes.msg, 3) this.$message.success(loginRes.msg, 3)
}) })
getSettings().then(result => { //
const settings = result.data.data
this.setSettings(settings)
})
} else { } else {
console.log("登录失败") console.log("登录失败")
this.error = loginRes.message this.error = loginRes.message

View File

@ -0,0 +1,23 @@
// 中台用户路由
// 视图组件
const view = {
tabs: () => import('@/layouts/tabs'),
blank: () => import('@/layouts/BlankView'),
page: () => import('@/layouts/PageView')
}
// 路由组件注册
const BaseAdminRouterMap = {
Admin:{
name: '用户管理',
icon: 'idcard',
component: view.page,
authority: {
permission:[''],
}
},
}
export default BaseAdminRouterMap

View File

@ -14,7 +14,9 @@ const BaseAdminRouterMap = {
name: '用户管理', name: '用户管理',
icon: 'idcard', icon: 'idcard',
component: view.page, component: view.page,
authority: ['Admin-All'] authority: {
permission:[''],
}
}, },
} }

View File

@ -14,7 +14,9 @@ const BaseCompanyRouterMap = {
name: '公司管理', name: '公司管理',
icon: 'idcard', icon: 'idcard',
component: view.page, component: view.page,
authority: ['Service-All'] authority: {
permission:[''],
}
}, },
} }

View File

@ -14,7 +14,9 @@ const BaseConfigRouterMap = {
name: '项目管理', name: '项目管理',
icon: 'idcard', icon: 'idcard',
component: view.page, component: view.page,
authority: ['Config-All'] authority: {
permission:[],
}
}, },
} }

View File

@ -14,7 +14,9 @@ const BaseServiceRouterMap = {
name: '服务管理', name: '服务管理',
icon: 'idcard', icon: 'idcard',
component: view.page, component: view.page,
authority: ['Service-All'] authority: {
permission:[''],
}
}, },
} }

View File

@ -169,29 +169,39 @@ const view = {
name: '报工管理', name: '报工管理',
icon: 'idcard', icon: 'idcard',
component: view.page, component: view.page,
authority: ['WorkReport-All'] authority: {
permission:['']
}
}, },
WorkReporList:{ WorkReporList:{
name: '报工列表', name: '报工列表',
component: () => import('@/pages/base/plan/WorkReporList'), component: () => import('@/pages/base/plan/WorkReporList'),
authority: ['WorkReport-All','WorkRepor-List'] authority: {
permission:[''],
}
}, },
Payroll:{ Payroll:{
name: '工资管理', name: '工资管理',
icon: 'idcard', icon: 'idcard',
component: view.page, component: view.page,
authority: ['Payroll-All'] authority: {
permission: ['Payroll-All'],
}
}, },
PayrollList:{ PayrollList:{
name: '工资列表', name: '工资列表',
component: () => import('@/pages/base/plan/PayrollList'), component: () => import('@/pages/base/plan/PayrollList'),
authority: ['Payroll-All','Payroll-List'] authority: {
permission:['Payroll-All','Payroll-List'],
}
}, },
PayrollSettings:{ PayrollSettings:{
name: '工资设置', name: '工资设置',
component: () => import('@/pages/base/plan/PayrollSettings'), component: () => import('@/pages/base/plan/PayrollSettings'),
authority: ['Payroll-All','Payroll-Settings'] authority: {
permission:['Payroll-All','Payroll-Settings'],
}
}, },
} }

View File

@ -52,10 +52,8 @@ const loginGuard = (to, from, next, options) => {
*/ */
const authorityGuard = (to, from, next, options) => { const authorityGuard = (to, from, next, options) => {
// console.log("进入authorityGuard权限守卫")
const {store, message} = options const {store, message} = options
const permissions = store.getters['account/permissions'] // 获取权限数据 const permissions = store.getters['account/permissions'] // 获取权限数据
console.log("store.getters['account/permissions']:", permissions)
if (!hasAuthority(to, permissions)) { // 判断是否有权限 if (!hasAuthority(to, permissions)) { // 判断是否有权限
// 如果没有权限跳转到403页面 // 如果没有权限跳转到403页面
message.warning(`对不起,您无权访问页面: ${to.fullPath},请联系管理员`) message.warning(`对不起,您无权访问页面: ${to.fullPath},请联系管理员`)

View File

@ -1,6 +1,46 @@
import Vue from 'vue' import Vue from 'vue'
import Router from 'vue-router' import Router from 'vue-router'
import {formatRoutes} from '@/utils/routerUtil' // 引入路由格式化工具 import { formatRoutes } from '@/utils/routerUtil' // 引入路由格式化工具
// -------------------------------- 以下为刷新页面时,重新加载路由 权限 用户信息的代码 --------------------------------
import { getUserInfo, getRoutesConfig, getPermission,getSettings } from '@/services/base/user' // 刷新用户信息
import { loadRoutes } from '@/utils/routerUtil'
import store from '@/store' // 引入vuex store 实例
import xsrfHeaderName from '@/utils/request' // 引入request
import Cookie from 'js-cookie'
// 如果cookie中存在认证信息
const Authorization = Cookie.get(xsrfHeaderName).Authorization
if (Authorization != null) {
getUserInfo().then(result => { // 获取用户信息
const UserInfo = result.data.data.user_info
console.log("UserInfo: ", UserInfo)
store.commit('account/setRoutesConfig', UserInfo) // 将用户信息存入vuex
})
getPermission().then(result => { // 获取权限
const Permission = result.data.data.permission
console.log("Permission: ", Permission)
store.commit('account/setPermissions', Permission) // 将权限信息存入vuex
})
getRoutesConfig().then(result => { // 获取路由配置
const routesConfig = result.data.data
console.log("routesConfig: ", routesConfig)
store.commit('account/setRoutesConfig', routesConfig) // 将路由配置信息存入vuex
loadRoutes([routesConfig]) // 加载路由
})
getSettings().then(result => { // 获取系统配置
const settings = result.data.data
store.commit('account/setRoutesConfig', settings) // 将系统配置信息存入vuex
})
}
// -------------------------------- 以上为刷新页面时,重新加载路由 权限 用户信息的代码 --------------------------------
Vue.use(Router) Vue.use(Router)
@ -14,8 +54,6 @@ const loginIgnore = { // 登录白名单
* @returns {boolean} * @returns {boolean}
*/ */
includes(route) { // 判断路由是否包含在该配置中 includes(route) { // 判断路由是否包含在该配置中
console.log("route", route)
console.log("this.names.includes(route.name) || this.paths.includes(route.path)",this.names.includes(route.name) || this.paths.includes(route.path))
return this.names.includes(route.name) || this.paths.includes(route.path) // 返回true则不需要登录拦截 return this.names.includes(route.name) || this.paths.includes(route.path) // 返回true则不需要登录拦截
} }
} }
@ -37,4 +75,4 @@ function initRouter(isAsync) { // 初始化路由
formatRoutes(options.routes) // 格式化路由 formatRoutes(options.routes) // 格式化路由
return new Router(options) // 返回路由实例 return new Router(options) // 返回路由实例
} }
export {loginIgnore, initRouter} // 导出路由配置和初始化路由方法 export { loginIgnore, initRouter } // 导出路由配置和初始化路由方法

View File

@ -1,7 +1,4 @@
import BASE_URL from '@/services/api.js'; import BASE_URL from '@/services/base/api.js';
module.exports = { module.exports = {
LOGIN: `${BASE_URL}/AdminUser/v1/login`, LOGIN: `${BASE_URL}/AdminUser/v1/login`,
ROUTES: `${BASE_URL}/AdminUser/v1/routers`,
USERINFO: `${BASE_URL}/AdminUser/v1/userinfo`,
PERMISSION: `${BASE_URL}/AdminUser/v1/permission`,
} }

View File

@ -4,8 +4,10 @@
const BASE_URL = process.env.VUE_APP_API_BASE_URL // 获取环境变量VUE_APP_API_BASE_URL const BASE_URL = process.env.VUE_APP_API_BASE_URL // 获取环境变量VUE_APP_API_BASE_URL
module.exports = { module.exports = {
BASE_URL,
LOGIN: `${BASE_URL}/AdminUser/v1/login`, LOGIN: `${BASE_URL}/AdminUser/v1/login`,
ROUTES: `${BASE_URL}/AdminUser/v1/routers`, ROUTES: `${BASE_URL}/AdminUser/v1/routers`,
USERINFO: `${BASE_URL}/AdminUser/v1/userinfo`, USERINFO: `${BASE_URL}/AdminUser/v1/userinfo`,
PERMISSION: `${BASE_URL}/AdminUser/v1/permission`, PERMISSION: `${BASE_URL}/AdminUser/v1/permission`,
SETTINGS: `${BASE_URL}/AdminUser/v1/settings`,
} }

View File

@ -1,12 +0,0 @@
// import {GOODS, GOODS_COLUMNS} from './api' // 引入api.js中的常量
// import {METHOD, request} from '@/utils/request'
// export async function goodsList(params) {
// return request(GOODS, METHOD.GET, params)
// }
// export async function goodsColumns() {
// return request(GOODS_COLUMNS, METHOD.GET)
// }
// export default {goodsList, goodsColumns}

View File

@ -1,4 +1,4 @@
import {LOGIN, ROUTES, USERINFO,PERMISSION} from '@/services/base/api' import {LOGIN, ROUTES, USERINFO,PERMISSION,SETTINGS} from '@/services/base/api'
import {request, METHOD, removeAuthorization} from '@/utils/request' import {request, METHOD, removeAuthorization} from '@/utils/request'
/** /**
* 登录服务 * 登录服务
@ -19,7 +19,7 @@ export async function login(name, password) {
* @returns {Promise<AxiosResponse<T>>} * @returns {Promise<AxiosResponse<T>>}
*/ */
export async function getUserInfo() { // 获取用户信息 export async function getUserInfo() { // 获取用户信息
const userId = parseInt(localStorage.getItem(process.env.VUE_APP_USER_KEY)) // 获取用户id并转换为整数 const userId = parseInt(localStorage.getItem(process.env.VUE_APP_UID_KEY)) // 获取用户id并转换为整数
return request(USERINFO, METHOD.POST, { return request(USERINFO, METHOD.POST, {
uid: userId uid: userId
}) })
@ -30,7 +30,7 @@ export async function getUserInfo() { // 获取用户信息
* @returns {Promise<AxiosResponse<T>>} * @returns {Promise<AxiosResponse<T>>}
*/ */
export async function getRoutesConfig() { // 获取路由配置 export async function getRoutesConfig() { // 获取路由配置
const userId = parseInt(localStorage.getItem(process.env.VUE_APP_USER_KEY)) // 获取用户id并转换为整数 const userId = parseInt(localStorage.getItem(process.env.VUE_APP_UID_KEY)) // 获取用户id并转换为整数
return request(ROUTES, METHOD.POST, { return request(ROUTES, METHOD.POST, {
uid:userId uid:userId
}) })
@ -42,23 +42,39 @@ export async function getRoutesConfig() { // 获取路由配置
* @returns {Promise<AxiosResponse<T>>} * @returns {Promise<AxiosResponse<T>>}
*/ */
export async function getPermission() { // 获取权限配置 export async function getPermission() { // 获取权限配置
const userId = parseInt(localStorage.getItem(process.env.VUE_APP_USER_KEY)) // 获取用户id并转换为整数 const userId = parseInt(localStorage.getItem(process.env.VUE_APP_UID_KEY)) // 获取用户id并转换为整数
return request(PERMISSION, METHOD.POST, { return request(PERMISSION, METHOD.POST, {
uid:userId uid:userId
}) })
} }
/**
* 获取用户设置
* @param uid
* @returns {Promise<AxiosResponse<Tuple>>}
*/
export async function getSettings() { // 获取用户设置
const userId = parseInt(localStorage.getItem(process.env.VUE_APP_UID_KEY)) // 获取用户id并转换为整数
return request(SETTINGS, METHOD.POST, {
uid:userId
})
}
/** /**
* 退出登录 * 退出登录
*/ */
export function logout() { export function logout() {
localStorage.removeItem(process.env.VUE_APP_ROUTES_KEY) // 删除路由配置 localStorage.removeItem(process.env.VUE_APP_ROUTES_KEY) // 删除路由配置
localStorage.removeItem(process.env.VUE_APP_PERMISSIONS_KEY) // 删除权限配置 localStorage.removeItem(process.env.VUE_APP_PERMISSIONS_KEY) // 删除权限配置
localStorage.removeItem(process.env.VUE_APP_USER_KEY) // 删除用户id localStorage.removeItem(process.env.VUE_APP_USER_KEY) // 删除用户信息
localStorage.removeItem(process.env.VUE_APP_UID_KEY) // 删除用户id
removeAuthorization() removeAuthorization()
} }
export default { export default {
login, login,
logout, logout,
getRoutesConfig getRoutesConfig,
getPermission,
getUserInfo,
getSettings
} }

View File

@ -1,7 +1,7 @@
import userService from './base/user' import userService from './base/user'
import dataSource from './base/dataSource'
export { export {
userService, userService,
dataSource
} }

View File

@ -1,16 +1,30 @@
export default { export default {
namespaced: true, namespaced: true,
state: { state: {
uid: 0,
user: undefined, // 用户信息 user: undefined, // 用户信息
permissions: null, // 权限 permissions: undefined, // 权限
routesConfig: null // 路由配置 routesConfig: undefined, // 路由配置
settings: undefined // 用户配置
}, },
getters: { getters: {
uid: state => { // 用户id
if (!state.uid) { // 如果没有用户uid
try {
const uid = localStorage.getItem(process.env.VUE_APP_UID_KEY) // 获取用户id
state.uid = uid // 将用户信息赋值给state.user
} catch (e) { // 捕获异常
console.error(e)
}
}
return state.uid // 如果有用户信息,直接返回
},
user: state => { // 用户信息 user: state => { // 用户信息
if (!state.user) { // 如果没有用户信息 if (!state.user) { // 如果没有用户信息
try { try {
const user = localStorage.getItem(process.env.VUE_APP_USER_KEY) // 获取用户信息 const user = localStorage.getItem(process.env.VUE_APP_USER_KEY) // 获取用户信息
state.user = user // 将用户信息赋值给state.user state.user = JSON.parse(user) // 将用户信息赋值给state.user
state.user = state.user ? state.user : [] // 如果用户信息为空,赋值为空对象
} catch (e) { // 捕获异常 } catch (e) { // 捕获异常
console.error(e) console.error(e)
} }
@ -24,7 +38,7 @@ export default {
state.permissions = JSON.parse(permissions) // 将权限赋值给state.permissions state.permissions = JSON.parse(permissions) // 将权限赋值给state.permissions
state.permissions = state.permissions ? state.permissions : [] // 如果state.permissions为空则赋值为空数组 state.permissions = state.permissions ? state.permissions : [] // 如果state.permissions为空则赋值为空数组
} catch (e) { // 捕获异常 } catch (e) { // 捕获异常
console.error(e.message) // console.error(e.message)
} }
} }
return state.permissions // 如果有权限,则返回权限 return state.permissions // 如果有权限,则返回权限
@ -41,12 +55,29 @@ export default {
} }
} }
return state.routesConfig // 如果有路由配置,则返回路由配置 return state.routesConfig // 如果有路由配置,则返回路由配置
},
settings: state => { // 用户配置
if (!state.settings) { // 如果没有用户配置
try {
const settings = localStorage.getItem(process.env.VUE_APP_USER_SETTINGS_KEY) // 获取用户配置
state.settings = JSON.parse(settings) // 将字符串转换为json对象
state.settings = state.settings ? state.settings : {} // 如果state.settings为null则赋值为空对象
} catch (e) { // 捕获异常
console.error(e.message)
}
}
return state.settings // 如果有用户配置,则返回用户配置
} }
}, },
mutations: { mutations: {
setUid (state, uid) { // 设置用户uid
state.uid = uid
localStorage.setItem(process.env.VUE_APP_UID_KEY, JSON.stringify(uid))// 将所有用户信息存储到process.env.VUE_APP_UID_KEY key中
},
setUser (state, user) { // 设置用户信息 setUser (state, user) { // 设置用户信息
state.user = user state.user = user
localStorage.setItem(process.env.VUE_APP_USER_KEY, user)// 将所有用户信息存储到process.env.VUE_APP_USER_KEY中 localStorage.setItem(process.env.VUE_APP_USER_KEY, JSON.stringify(user))// 将所有用户信息存储到process.env.VUE_APP_USER_KEY中
}, },
setPermissions(state, permissions) { // 设置权限 setPermissions(state, permissions) { // 设置权限
state.permissions = permissions state.permissions = permissions
@ -54,8 +85,11 @@ export default {
}, },
setRoutesConfig(state, routesConfig) { // 设置路由配置 setRoutesConfig(state, routesConfig) { // 设置路由配置
state.routesConfig = routesConfig state.routesConfig = routesConfig
console.log("存入路由配置:", routesConfig)
localStorage.setItem(process.env.VUE_APP_ROUTES_KEY, JSON.stringify(routesConfig)) // 将所有路由信息存储到process.env.VUE_APP_ROUTES_KEY中 localStorage.setItem(process.env.VUE_APP_ROUTES_KEY, JSON.stringify(routesConfig)) // 将所有路由信息存储到process.env.VUE_APP_ROUTES_KEY中
},
setSettings(state, settings) { // 设置用户配置
state.settings = settings
localStorage.setItem(process.env.VUE_APP_USER_SETTINGS_KEY, JSON.stringify(settings)) // 将所有用户配置信息存储到process.env.VUE_APP_USER_SETTINGS_KEY中
} }
} }
} }

View File

@ -11,8 +11,17 @@
* @param roles 用户角色集合 * @param roles 用户角色集合
* @returns {boolean} * @returns {boolean}
*/ */
function hasAuthority() { // 权限校验 function hasAuthority(to, permissions) { // 权限校验
// 循环 to.meta.authority.permission 集合
if (to.meta && to.meta.authority.permission.length > 0) {
for (let i = 0; i < to.meta.authority.permission.length; i++) {
// 判断用户权限集合中是否包含 to.meta.authority.permission 中的权限
if (permissions.includes(to.meta.authority.permission[i])) {
return false
}
}
}
// 如果 to.meta.authority.permission 匹配到了 permissions 中的某个权限就返回false
return true // 如果都满足返回true return true // 如果都满足返回true
} }

View File

@ -33,6 +33,7 @@ const METHOD = {
* @returns {Promise<AxiosResponse<T>>} * @returns {Promise<AxiosResponse<T>>}
*/ */
async function request(url, method, params, config) { // 请求方法 async function request(url, method, params, config) { // 请求方法
axios.defaults.headers.common[xsrfHeaderName] = Cookie.get(xsrfHeaderName)
switch (method) { switch (method) {
case METHOD.GET: case METHOD.GET:
return axios.get(url, {params, ...config}) return axios.get(url, {params, ...config})

View File

@ -1,5 +1,5 @@
import routerMap from '@/router/async/router.map' import routerMap from '@/router/async/router.map'
import {mergeI18nFromRoutes} from '@/utils/i18n' import { mergeI18nFromRoutes } from '@/utils/i18n'
import Router from 'vue-router' import Router from 'vue-router'
import deepMerge from 'deepmerge' import deepMerge from 'deepmerge'
import basicOptions from '@/router/async/config.async' import basicOptions from '@/router/async/config.async'
@ -16,7 +16,7 @@ let appOptions = {
* @param options * @param options
*/ */
function setAppOptions(options) { // 设置应用配置 function setAppOptions(options) { // 设置应用配置
const {router, store, i18n} = options // 获取路由、状态管理、国际化 const { router, store, i18n } = options // 获取路由、状态管理、国际化
appOptions.router = router // 路由 appOptions.router = router // 路由
appOptions.store = store // 状态管理 appOptions.store = store // 状态管理
appOptions.i18n = i18n // 国际化 appOptions.i18n = i18n // 国际化
@ -34,14 +34,14 @@ function parseRoutes(routesConfig, routerMap) { // 解析路由
let router = undefined, routeCfg = {} // 初始化路由和路由配置 let router = undefined, routeCfg = {} // 初始化路由和路由配置
if (typeof item === 'string') { // 如果路由配置是字符串 if (typeof item === 'string') { // 如果路由配置是字符串
router = routerMap[item] // 从 routerMap 中获取路由 router = routerMap[item] // 从 routerMap 中获取路由
routeCfg = {path: (router && router.path) || item, router: item} // 路由配置获取路由的 path 和 router routeCfg = { path: (router && router.path) || item, router: item } // 路由配置获取路由的 path 和 router
} else if (typeof item === 'object') { // 如果路由配置是对象 } else if (typeof item === 'object') { // 如果路由配置是对象
router = routerMap[item.router] // 从 routerMap 中获取路由 router = routerMap[item.router] // 从 routerMap 中获取路由
routeCfg = item // 路由配置为 item routeCfg = item // 路由配置为 item
} }
if (!router) { // 如果没有获取到路由 或者是路由不为数组及对象 if (!router) { // 如果没有获取到路由 或者是路由不为数组及对象
console.warn(`can't find register for router ${routeCfg.router}, please register it in advance.`) // 打印警告 console.warn(`can't find register for router ${routeCfg.router}, please register it in advance.`) // 打印警告
router = typeof item === 'string' ? {path: item, name: item} : item // 如果路由配置是字符串,路由为 {path: item, name: item},否则为 item router = typeof item === 'string' ? { path: item, name: item } : item // 如果路由配置是字符串,路由为 {path: item, name: item},否则为 item
} }
// 从 router 和 routeCfg 解析路由 // 从 router 和 routeCfg 解析路由
const meta = { // 路由元信息 const meta = { // 路由元信息
@ -68,12 +68,12 @@ function parseRoutes(routesConfig, routerMap) { // 解析路由
} }
}) })
Object.assign(meta, cfgMeta) // 合并路由元信息和路由配置元信息 Object.assign(meta, cfgMeta) // 合并路由元信息和路由配置元信息
const route = { const route = {
path: routeCfg.path || router.path || routeCfg.router, // 路由路径 path: routeCfg.path || router.path || routeCfg.router, // 路由路径
name: routeCfg.name || router.name, // 路由名称 name: routeCfg.name || router.name, // 路由名称
component: router.component, // 路由组件 component: router.component, // 路由组件
redirect: routeCfg.redirect || router.redirect, // 重定向 redirect: routeCfg.redirect || router.redirect, // 重定向
meta: {...meta, authority: meta.authority || '*'} // 路由元信息 meta: { ...meta, authority: meta.authority || '*' } // 路由元信息
} }
if (routeCfg.invisible || router.invisible) { // 如果路由配置或者路由不可见 if (routeCfg.invisible || router.invisible) { // 如果路由配置或者路由不可见
route.meta.invisible = true route.meta.invisible = true
@ -86,14 +86,39 @@ function parseRoutes(routesConfig, routerMap) { // 解析路由
return routes return routes
} }
// 根据权限过滤路由
function filterRoutesConfig(routes, permissions) {
const res = []
routes.forEach(route => {
const tmp = { ...route }
if (hasPermission(permissions, tmp)) {
if (tmp.children) {
tmp.children = filterRoutesConfig(tmp.children, permissions)
}
res.push(tmp)
}
})
return res
}
// 判断是否有权限
function hasPermission(permissions, route) {
if (route.meta && route.meta.authority.permission) {
return permissions.some(permission => {
return route.meta.authority.permission === '' || route.meta.authority.permission === permission
})
} else {
return true
}
}
/** /**
* 加载路由 * 加载路由
* @param routesConfig {RouteConfig[]} 路由配置 * @param routesConfig {RouteConfig[]} 路由配置
*/ */
function loadRoutes(routesConfig) { // 加载路由 function loadRoutes(routesConfig) { // 加载路由
console.log("加载路由")
console.log("+++++routesConfig:",routesConfig)
console.log("+++++arguments:",arguments)
//兼容 0.6.1 以下版本 //兼容 0.6.1 以下版本
/*************** 兼容 version < v0.6.1 *****************/ /*************** 兼容 version < v0.6.1 *****************/
@ -110,24 +135,28 @@ function loadRoutes(routesConfig) { // 加载路由
/*************** 兼容 version < v0.6.1 *****************/ /*************** 兼容 version < v0.6.1 *****************/
// 应用配置 // 应用配置
const {router, store, i18n} = appOptions const { router, store, i18n } = appOptions
const Permission = store.getters['account/permissions'] // 获取权限
console.log("======Permission:",Permission)
if (routesConfig) { // 如果routesConfig已经存在
store.commit('account/setRoutesConfig', routesConfig) // 通过store的account模块的setRoutesConfig方法更新路由配置
} else {
routesConfig = store.getters['account/routesConfig'] // 通过store的account模块的routesConfig方法获取路由配置
}
// 如果 routesConfig 有值,则更新到本地,否则从本地获取 // 如果 routesConfig 有值,则更新到本地,否则从本地获取
console.log("=====setRoutesConfig:", routesConfig) console.log("=====setRoutesConfig:", routesConfig)
if (routesConfig) { // 如果routesConfig已经存在 // 根据权限过滤路由配置
console.log("routesConfig存在store.commit('account/setRoutesConfig', routesConfig)") const filteredRoutesConfig = filterRoutesConfig(routesConfig, Permission) // 根据权限过滤路由配置
store.commit('account/setRoutesConfig', routesConfig) // 通过store的account模块的setRoutesConfig方法更新路由配置 console.log("=====filteredRoutesConfig:", filteredRoutesConfig)
} else { // routesConfig = filteredRoutesConfig // 路由配置等于过滤后的路由配置
console.log("routesConfig不存在routesConfig = store.state.account.routesConfig")
routesConfig = store.getters['account/routesConfig'] // 通过store的account模块的routesConfig方法获取路由配置
console.log("=====getRoutesConfig:", routesConfig)
}
// 如果开启了异步路由,则加载异步路由配置 // 如果开启了异步路由,则加载异步路由配置
const asyncRoutes = store.state.setting.asyncRoutes // 获取store的setting模块的asyncRoutes const asyncRoutes = store.state.setting.asyncRoutes // 获取store的setting模块的asyncRoutes
console.log("asyncRoutes",asyncRoutes)
if (asyncRoutes) { // 如果动态路由存在 if (asyncRoutes) { // 如果动态路由存在
console.log("routesConfig && routesConfig.length > 0",routesConfig.length > 0) console.log("routesConfig && routesConfig.length > 0", routesConfig.length > 0)
if (routesConfig && routesConfig.length > 0) { // 如果本地路由配置存在 并且 数量大于0 if (routesConfig && routesConfig.length > 0) { // 如果本地路由配置存在 并且 数量大于0
const routes = parseRoutes(routesConfig, routerMap) // 解析路由 const routes = parseRoutes(routesConfig, routerMap) // 解析路由
// 合并路由 生成路由表 // 合并路由 生成路由表
@ -135,9 +164,12 @@ function loadRoutes(routesConfig) { // 加载路由
// 格式化路由 // 格式化路由
formatRoutes(finalRoutes) formatRoutes(finalRoutes)
console.log('最终路由表finalRoutes:', finalRoutes) // 最终路由表 console.log('最终路由表finalRoutes:', finalRoutes) // 最终路由表
router.options = {...router.options, routes: finalRoutes} // 路由配置 router.options = { ...router.options, routes: finalRoutes } // 路由配置
router.matcher = new Router({...router.options, routes:[]}).matcher // 重置路由 router.matcher = new Router({ ...router.options, routes: [] }).matcher // 重置路由
router.addRoutes(finalRoutes) // 添加路由 // router.addRoutes(finalRoutes) // 添加路由
for (let x of finalRoutes) {
router.addRoute(x)
}
} }
} }
// 提取路由国际化数据 // 提取路由国际化数据
@ -150,6 +182,8 @@ function loadRoutes(routesConfig) { // 加载路由
} }
} }
/** /**
* 合并路由 * 合并路由
* @param target {Route[]} * @param target {Route[]}
@ -175,7 +209,7 @@ function deepMergeRoutes(target, source) {
const routesMap = {} // 路由映射表 const routesMap = {} // 路由映射表
routes.forEach(item => { // 遍历路由 routes.forEach(item => { // 遍历路由
routesMap[item.path] = { // 将路由添加到路由映射表中 routesMap[item.path] = { // 将路由添加到路由映射表中
...item, ...item,
children: item.children ? mapRoutes(item.children) : undefined // 如果路由有子路由则递归调用mapRoutes方法 children: item.children ? mapRoutes(item.children) : undefined // 如果路由有子路由则递归调用mapRoutes方法
} }
}) })
@ -207,7 +241,7 @@ function deepMergeRoutes(target, source) {
*/ */
function formatRoutes(routes) { // 格式化路由 function formatRoutes(routes) { // 格式化路由
routes.forEach(route => { // 遍历路由 routes.forEach(route => { // 遍历路由
const {path} = route // 获取路由的path const { path } = route // 获取路由的path
if (!path.startsWith('/') && path !== '*') { // 如果路由的path不是以/开头 并且 不是* if (!path.startsWith('/') && path !== '*') { // 如果路由的path不是以/开头 并且 不是*
route.path = '/' + path // 将路由的path添加/ route.path = '/' + path // 将路由的path添加/
} }
@ -223,16 +257,16 @@ function formatRoutes(routes) { // 格式化路由
function formatAuthority(routes, pAuthorities = []) { // 格式化路由的权限配置 function formatAuthority(routes, pAuthorities = []) { // 格式化路由的权限配置
routes.forEach(route => { // 遍历路由 routes.forEach(route => { // 遍历路由
const meta = route.meta // 获取路由的meta const meta = route.meta // 获取路由的meta
const defaultAuthority = pAuthorities[pAuthorities.length - 1] || {permission: '*'} // 获取默认权限 首先获取父级路由权限配置集合的最后一个元素,如果没有则获取{permission: '*'} const defaultAuthority = pAuthorities[pAuthorities.length - 1] || { permission: '*' } // 获取默认权限 首先获取父级路由权限配置集合的最后一个元素,如果没有则获取{permission: '*'}
if (meta) { // 如果meta存在 if (meta) { // 如果meta存在
let authority = {} // 权限 let authority = {} // 权限
if (!meta.authority) { // 如果meta.authority不存在 if (!meta.authority) { // 如果meta.authority不存在
authority = defaultAuthority // 权限为默认权限 authority = defaultAuthority // 权限为默认权限
}else if (typeof meta.authority === 'string') { // 如果meta.authority是字符串 } else if (typeof meta.authority === 'string') { // 如果meta.authority是字符串
authority.permission = meta.authority // 权限的permission为meta.authority authority.permission = meta.authority // 权限的permission为meta.authority
} else if (typeof meta.authority === 'object') { // 如果meta.authority是对象 } else if (typeof meta.authority === 'object') { // 如果meta.authority是对象
authority = meta.authority // 权限为meta.authority authority = meta.authority // 权限为meta.authority
const {role} = authority // 获取权限的role const { role } = authority // 获取权限的role
if (typeof role === 'string') { // 如果权限的role是字符串 if (typeof role === 'string') { // 如果权限的role是字符串
authority.role = [role] // 权限的role为数组 authority.role = [role] // 权限的role为数组
} }
@ -243,7 +277,7 @@ function formatAuthority(routes, pAuthorities = []) { // 格式化路由的权
meta.authority = authority // 将权限赋值给meta.authority meta.authority = authority // 将权限赋值给meta.authority
} else { // 如果meta不存在 } else { // 如果meta不存在
const authority = defaultAuthority // 权限为默认权限 const authority = defaultAuthority // 权限为默认权限
route.meta = {authority} // 将权限赋值给meta route.meta = { authority } // 将权限赋值给meta
} }
route.meta.pAuthorities = pAuthorities // 将父级路由权限配置集合赋值给meta.pAuthorities route.meta.pAuthorities = pAuthorities // 将父级路由权限配置集合赋值给meta.pAuthorities
if (route.children) { // 如果路由有子路由 递归调用formatAuthority方法 if (route.children) { // 如果路由有子路由 递归调用formatAuthority方法
@ -269,8 +303,8 @@ function getI18nKey(path) { // 从路由 path 解析 i18n key
* @param options * @param options
*/ */
function loadGuards(guards, options) { // 加载导航守卫 guards function loadGuards(guards, options) { // 加载导航守卫 guards
const {beforeEach, afterEach} = guards // 解构出 beforeEach 和 afterEach const { beforeEach, afterEach } = guards // 解构出 beforeEach 和 afterEach
const {router} = options // 解构出 router const { router } = options // 解构出 router
beforeEach.forEach(guard => { // 遍历 beforeEach beforeEach.forEach(guard => { // 遍历 beforeEach
if (guard && typeof guard === 'function') { // 如果guard存在 并且 guard是函数 if (guard && typeof guard === 'function') { // 如果guard存在 并且 guard是函数
router.beforeEach((to, from, next) => guard(to, from, next, options)) // 调用router.beforeEach方法 router.beforeEach((to, from, next) => guard(to, from, next, options)) // 调用router.beforeEach方法
@ -283,4 +317,4 @@ function loadGuards(guards, options) { // 加载导航守卫 guards
}) })
} }
export {parseRoutes, loadRoutes, formatAuthority, getI18nKey, loadGuards, deepMergeRoutes, formatRoutes, setAppOptions} export { parseRoutes, loadRoutes, formatAuthority, getI18nKey, loadGuards, deepMergeRoutes, formatRoutes, setAppOptions }