继续整理系统开发前的准备

This commit is contained in:
zxx 2022-10-15 16:43:11 +08:00
parent b5bf802ab2
commit e1a5515432
20 changed files with 368 additions and 190 deletions

3
.env
View File

@ -1,9 +1,12 @@
VUE_APP_PUBLIC_PATH=/
VUE_APP_BEID=1
VUE_APP_NAME=Admin
VUE_APP_ROUTES_KEY=admin.routes
VUE_APP_PERMISSIONS_KEY=admin.permissions
VUE_APP_UID_KEY=admin.uid
VUE_APP_USER_KEY=admin.user
VUE_APP_PROJECT_KEY=admin.project
VUE_APP_COMPANY_KEY=admin.company
VUE_APP_SETTING_KEY=admin.setting
VUE_APP_USER_SETTINGS_KEY=admin.user.settings
VUE_APP_TBAS_KEY=admin.tabs

View File

@ -17,8 +17,8 @@ export default {
locale: {}
}
},
created () {
this.setHtmlTitle() // html
this.setLanguage(this.lang) //
enquireScreen(isMobile => this.setDevice(isMobile)) //
},
@ -49,7 +49,8 @@ export default {
}
},
computed: {
...mapState('setting', ['layout', 'theme', 'weekMode', 'lang'])
...mapState('setting', ['layout', 'theme', 'weekMode', 'lang']),
...mapState('account', ['project']) ,
},
methods: {
...mapMutations('setting', ['setDevice']),
@ -76,9 +77,10 @@ export default {
}
},
setHtmlTitle() { // html
const project = this.project
const route = this.$route //
const key = route.path === '/' ? 'home.name' : getI18nKey(route.matched[route.matched.length - 1].path) // i18n keywords home.name i18n keywords
document.title = process.env.VUE_APP_NAME + ' | ' + this.$t(key) // html process.env.VUE_APP_NAME this.$t(key) i18n keywords
document.title = project.project_name + ' | ' + this.$t(key) // html process.env.VUE_APP_NAME this.$t(key) i18n keywords
},
popContainer() { //
return document.getElementById("popContainer") //

View File

@ -26,10 +26,11 @@ export default {
},
methods: {
backHome() {
if (this.homeRoute) {
this.$router.push(this.homeRoute)
}
this.$emit('backHome', this.type)
this.$router.push('/')
// if (this.homeRoute) {
// this.$router.push(this.homeRoute)
// }
// this.$emit('backHome', this.type)
}
}
}

View File

@ -10,6 +10,7 @@
<a-icon v-if="item.icon" :type="item.icon" />
<span>{{ item.text }}</span>
</a-menu-item>
</a-menu>
</template>

View File

@ -1,21 +1,29 @@
<template>
<a-layout-sider :theme="sideTheme" :class="['side-menu', 'beauty-scroll', isMobile ? null : 'shadow']" width="256px" :collapsible="collapsible" v-model="collapsed" :trigger="null">
<a-layout-sider :theme="sideTheme" :class="['side-menu', 'beauty-scroll', isMobile ? null : 'shadow']" width="256px"
:collapsible="collapsible" v-model="collapsed" :trigger="null">
<div :class="['logo', theme]">
<!-- PC端 -->
<router-link to="/dashboard/workplace">
<img src="@/assets/img/logo.png">
<h1>{{systemName}}</h1>
<img width="80" v-if="!company.company_info.logo" :src="project.project_logo">
<h1 v-if="!company.company_info.name">{{project.project_name}}</h1>
<img width="80" v-if="company.company_info.logo" :src="company.company_info.logo">
<h1 v-if="company.company_info.name">{{company.company_info.name}}</h1>
</router-link>
</div>
<i-menu :theme="theme" :collapsed="collapsed" :options="menuData" @select="onSelect" class="menu"/>
<i-menu :theme="theme" :collapsed="collapsed" :options="menuData" @select="onSelect" class="menu" />
<div class="footer" style="display: none;">
<page-footer />
</div>
</a-layout-sider>
</template>
<script>
import IMenu from './menu'
import {mapState} from 'vuex'
import { mapState } from 'vuex'
import PageFooter from '@/layouts/footer/PageFooter' //
export default {
name: 'SideMenu',
components: {IMenu},
components: { IMenu, PageFooter },
props: {
collapsible: {
type: Boolean,
@ -37,14 +45,25 @@ export default {
default: 'dark'
}
},
data() {
return {
// Project :localStorage.getItem(process.env.VUE_APP_PROJECT_KEY),
}
},
beforeMount() {
},
computed: {
...mapState('account', ['project', 'company']), // ,
sideTheme() {
console.log("localStorage:", this.project)
return this.theme == 'light' ? this.theme : 'dark'
},
...mapState('setting', ['isMobile', 'systemName'])
},
methods: {
onSelect (obj) {
onSelect(obj) {
this.$emit('menuSelect', obj)
}
}
@ -53,4 +72,15 @@ export default {
<style lang="less" scoped>
@import "index";
.footer {
color: blanchedalmond !important;
width: 100%;
text-align: center;
//
position: absolute;
bottom: 0;
}
</style>

View File

@ -9,7 +9,7 @@
height: 64px;
position: relative;
line-height: 64px;
padding-left: 24px;
padding-left: 15px;
-webkit-transition: all .3s;
transition: all .3s;
overflow: hidden;
@ -28,7 +28,7 @@
vertical-align: middle;
}
img{
width: 32px;
width: 50px;
vertical-align: middle;
}
}

View File

@ -1,4 +1,5 @@
// 此配置为系统默认设置需修改的设置项在src/config/config.js中添加修改项即可。也可直接在此文件中修改。
module.exports = {
lang: 'CN', //语言,可选 CN(简体)、HK(繁体)、US(英语),也可扩展其它语言
theme: { //主题
@ -18,7 +19,7 @@ module.exports = {
cachePage: true, //是否缓存页面数据仅多页签模式下生效true 缓存, false 不缓存
hideSetting: false, //隐藏设置抽屉true:隐藏false:不隐藏
systemName: 'MES生产管理系统', //系统名称
copyright: '2018 ICZER 工作室出品', //copyright
copyright: 'Project.copyright', //copyright
asyncRoutes: false, //异步加载路由true:开启false:不开启
showPageTitle: true, //是否显示页面标题PageLayout 布局中的页面标题true:显示false:不显示
filterMenu: true, //根据权限过滤菜单true:过滤false:不过滤

View File

@ -28,7 +28,7 @@
</div>
</a-layout-content>
<a-layout-footer style="padding: 0px">
<page-footer :link-list="footerLinks" :copyright="copyright" />
<page-footer :link-list="footerLinks" />
</a-layout-footer>
</a-layout>
</a-layout>

View File

@ -6,14 +6,14 @@
</template>
<script>
import PageFooter from '@/layouts/footer/PageFooter' //
import {mapState} from 'vuex' // vuex
import PageFooter from '@/layouts/footer/PageFooter'
import {mapState} from 'vuex'
export default {
name: 'CommonLayout', //
components: {PageFooter}, //
name: 'CommonLayout',
components: {PageFooter},
computed: {
...mapState('setting', ['footerLinks', 'copyright']) // vuex
...mapState('setting', ['footerLinks', 'copyright'])
}
}
</script>

View File

@ -1,20 +1,22 @@
<template>
<div class="footer">
<div class="links">
<a target="_blank" :key="index" :href="item.link ? item.link : 'javascript: void(0)'" v-for="(item, index) in linkList">
<a-icon v-if="item.icon" :type="item.icon"/>{{item.name}}
</a>
</div>
<div class="copyright">
Copyright<a-icon type="copyright" />{{copyright}}
<a-icon type="copyright" />{{project.copyright}} <br />
<a-icon type="copyright" />{{project.en_copyright}} <br />
</div>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: 'PageFooter',
props: ['copyright', 'linkList']
computed: {
...mapState('account', ['project']) ,
},
}
</script>

View File

@ -1,9 +1,13 @@
<template>
<a-layout-header :class="[headerTheme, 'admin-header']">
<div :class="['admin-header-wide', layout, pageWidth]">
<router-link v-if="isMobile || layout === 'head'" to="/" :class="['logo', isMobile ? null : 'pc', headerTheme]">
<img width="32" src="@/assets/img/logo.png" />
<h1 v-if="!isMobile">{{systemName}}</h1>
<!-- 如果是手机端 -->
<router-link v-if="isMobile || layout === 'head'" to="/dashboard/workplace" :class="['logo', isMobile ? null : 'pc', headerTheme]">
<img width="80" v-if="!company.company_info.logo" :src="project.project_logo">
<h1 v-if="!company.company_info.name">{{project.project_name}}</h1>
<img width="80" style="margin-right:5px;" v-if="company.company_info.logo" :src="company.company_info.logo">
<h1 v-if="company.company_info.name">{{company.company_info.name}}</h1>
</router-link>
<a-divider v-if="isMobile" type="vertical" />
<a-icon v-if="layout !== 'head'" class="trigger" :type="collapsed ? 'menu-unfold' : 'menu-fold'" @click="toggleCollapse"/>
@ -11,13 +15,15 @@
<i-menu class="head-menu" :theme="headerTheme" mode="horizontal" :options="menuData" @select="onSelect"/>
</div>
<div :class="['admin-header-right', headerTheme]">
<header-search class="header-item" @active="val => searchActive = val" />
<a-tooltip class="header-item" title="帮助文档" placement="bottom" >
<!-- 暂时先把搜索隐藏起来 -->
<header-search class="header-item" @active="val => searchActive = val" style="display:none" />
<!-- <a-tooltip class="header-item" title="帮助文档" placement="bottom" >
<a href="https://iczer.gitee.io/vue-antd-admin-docs/" target="_blank">
<a-icon type="question-circle-o" />
</a>
</a-tooltip>
<header-notice class="header-item"/>
</a-tooltip> -->
<!-- 暂时先把通知隐藏起来 -->
<header-notice class="header-item" style="display:none"/>
<header-avatar class="header-item"/>
<a-dropdown class="lang header-item">
<div>
@ -52,9 +58,14 @@ export default {
],
searchActive: false //
}
},
beforeCreate(){
},
computed: {
...mapState('setting', ['theme', 'isMobile', 'layout', 'systemName', 'lang', 'pageWidth']),
...mapState('setting', ['theme', 'isMobile', 'layout', 'lang', 'pageWidth']), // vuex settingthemeisMobilelayoutlangpageWidth
...mapState('account', ['project','company']), // ,
// vuex
headerTheme () { //
if (this.layout == 'side' && this.theme.mode == 'dark' && !this.isMobile) { //
@ -80,7 +91,7 @@ export default {
onSelect (obj) { //
this.$emit('menuSelect', obj) // menuSelect
},
...mapMutations('setting', ['setLang']) // vuex
...mapMutations('setting', ['setLang']), // vuex
}
}
</script>

View File

@ -2,40 +2,27 @@
<common-layout>
<div class="top">
<div class="header">
<img alt="logo" class="logo" src="@/assets/img/logo.png" />
<span class="title">{{systemName}}</span>
<img alt="logo" class="logo" :src="Project.project_logo" />
<span class="title">{{Project.project_name}}</span>
</div>
<div class="desc">Ant Design 是西湖区最具影响力的 Web 设计规范</div>
<div class="desc">{{Project.project_sub_title}}</div>
</div>
<div class="login">
<a-form
@submit="onSubmit"
:form="form"
>
<a-form @submit="onSubmit" :form="form">
<a-tabs size="large" :tabBarStyle="{textAlign: 'center'}" style="padding: 0 2px;">
<a-tab-pane tab="账户密码登录" key="1">
<a-alert type="error" :closable="true" v-show="error" :message="error" showIcon style="margin-bottom: 24px;" />
<a-alert type="error" :closable="true" v-show="error" :message="error" showIcon
style="margin-bottom: 24px;" />
<a-form-item>
<a-input
autocomplete="autocomplete"
size="large"
placeholder="admin"
v-decorator="['name', {rules: [{ required: true, message: '请输入账户名', whitespace: true}]}]"
>
<a-input autocomplete="autocomplete" size="large" placeholder="admin"
v-decorator="['name', {rules: [{ required: true, message: '请输入账户名', whitespace: true}]}]">
<!-- -->
<a-icon slot="prefix" type="user" />
</a-input>
</a-form-item>
<a-form-item>
<a-input
size="large"
placeholder="888888"
autocomplete="autocomplete"
type="password"
v-decorator="['password', {rules: [{ required: true, message: '请输入密码', whitespace: true}]}]"
>
<a-input size="large" placeholder="888888" autocomplete="autocomplete" type="password"
v-decorator="['password', {rules: [{ required: true, message: '请输入密码', whitespace: true}]}]">
<!-- -->
<a-icon slot="prefix" type="lock" />
</a-input>
@ -43,7 +30,7 @@
</a-tab-pane>
<a-tab-pane tab="手机号登录" key="2">
<a-form-item>
<a-input size="large" placeholder="mobile number" >
<a-input size="large" placeholder="mobile number">
<a-icon slot="prefix" type="mobile" />
</a-input>
</a-form-item>
@ -62,18 +49,19 @@
</a-tab-pane>
</a-tabs>
<div>
<a-checkbox :checked="true" >自动登录</a-checkbox>
<a-checkbox :checked="true">自动登录</a-checkbox>
<a style="float: right">忘记密码</a>
</div>
<a-form-item>
<a-button :loading="logging" style="width: 100%;margin-top: 24px" size="large" htmlType="submit" type="primary">登录</a-button>
<a-button :loading="logging" style="width: 100%;margin-top: 24px" size="large" htmlType="submit"
type="primary">登录</a-button>
</a-form-item>
<div>
其他登录方式
<a-icon class="icon" type="alipay-circle" />
<a-icon class="icon" type="taobao-circle" />
<a-icon class="icon" type="weibo-circle" />
<router-link style="float: right" to="/dashboard/workplace" >注册账户</router-link>
<router-link style="float: right" to="/dashboard/workplace">注册账户</router-link>
</div>
</a-form>
</div>
@ -82,10 +70,10 @@
<script>
import CommonLayout from '@/layouts/CommonLayout'
import {login,getUserInfo, getRoutesConfig,getPermission,getSettings} from '@/services/base/user'
import {setAuthorization} from '@/utils/request'
import {loadRoutes} from '@/utils/routerUtil'
import {mapMutations} from 'vuex'
import { login, getUserInfo, getRoutesConfig, getPermission, getSettings, getCompany, getProject } from '@/services/base/user'
import { setAuthorization } from '@/utils/request'
import { loadRoutes } from '@/utils/routerUtil'
import { mapMutations } from 'vuex'
@ -94,8 +82,8 @@ import {mapMutations} from 'vuex'
// import axios from 'axios'
export default {
name: 'Login',
components: {CommonLayout},
data () {
components: { CommonLayout },
data() {
return {
logging: false,
error: '',
@ -103,16 +91,24 @@ export default {
user: {
mobile: '18678390480',
password: '888888'
} ,
},
Project: [],
}
},
computed: {
systemName () {
return this.$store.state.setting.systemName
}
},
created(){
beforeMount() {
getProject().then(result => { //
this.Project = result.data.data
const project = result.data.data
this.setProject(project) // vuex
})
},
created() {
this.$nextTick(() => {
@ -127,9 +123,9 @@ export default {
},
methods: {
...mapMutations('account', ['setUid','setUser','setPermissions','setRoutesConfig','setSettings']),
...mapMutations('account', ['setUid', 'setUser', 'setPermissions', 'setRoutesConfig', 'setSettings', 'setCompany', 'setProject']),
onSubmit (e) {
onSubmit(e) {
e.preventDefault()
this.form.validateFields((err) => {
if (!err) {
@ -147,36 +143,47 @@ export default {
if (loginRes.code == 200) {
const uid = loginRes.data.uid
setAuthorization({token: loginRes.data.access_token, expireAt: new Date(loginRes.data.access_expire*1000)}) // token
setAuthorization({ token: loginRes.data.access_token, expireAt: new Date(loginRes.data.access_expire * 1000) }) // token
this.setUid(uid) // id
getUserInfo().then(result =>{ //
console.log("UserInforesult:",result)
getUserInfo().then(result => { //
if (result.data.data != null) {
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)
if (result.data.data != null) {
const Permission = result.data.data.setPermissions
this.setPermissions(Permission)
}
})
getRoutesConfig().then(result => { //
if (result.data.data != null) {
const routesConfig = result.data.data
this.setRoutesConfig(routesConfig)
loadRoutes([routesConfig])
this.$router.push('/dashboard/workplace')
this.$message.success(loginRes.msg, 3)
}
})
getSettings().then(result => { //
if (result.data.data != null) {
const settings = result.data.data
this.setSettings(settings)
}
})
getCompany().then(result => { //
if (result.data.data != null) {
const company = result.data.data
this.setCompany(company) // vuex
}
})
} else {
console.log("登录失败")
@ -188,20 +195,24 @@ export default {
</script>
<style lang="less" scoped>
.common-layout{
.common-layout {
.top {
text-align: center;
.header {
height: 44px;
line-height: 44px;
a {
text-decoration: none;
}
.logo {
height: 44px;
vertical-align: top;
margin-right: 16px;
}
.title {
font-size: 33px;
color: @title-color;
@ -211,6 +222,7 @@ export default {
top: 2px;
}
}
.desc {
font-size: 14px;
color: @text-color-second;
@ -218,17 +230,21 @@ export default {
margin-bottom: 40px;
}
}
.login{
.login {
width: 368px;
margin: 0 auto;
@media screen and (max-width: 576px) {
width: 95%;
}
@media screen and (max-width: 320px) {
.captcha-button{
.captcha-button {
font-size: 14px;
}
}
.icon {
font-size: 24px;
color: @text-color-second;
@ -242,5 +258,5 @@ export default {
}
}
}
}
}
</style>

View File

@ -5,7 +5,7 @@ import { formatRoutes } from '@/utils/routerUtil' // 引入路由格式化工具
// -------------------------------- 以下为刷新页面时,重新加载路由 权限 用户信息的代码 --------------------------------
import { getUserInfo, getRoutesConfig, getPermission,getSettings } from '@/services/base/user' // 刷新用户信息
import { getUserInfo, getRoutesConfig, getPermission, getSettings, getCompany, getProject } from '@/services/base/user' // 刷新用户信息
import { loadRoutes } from '@/utils/routerUtil'
import store from '@/store' // 引入vuex store 实例
import xsrfHeaderName from '@/utils/request' // 引入request
@ -15,28 +15,48 @@ const Authorization = Cookie.get(xsrfHeaderName).Authorization
if (Authorization != null) {
getUserInfo().then(result => { // 获取用户信息
if (result.data.data != null) {
const UserInfo = result.data.data.user_info
console.log("UserInfo: ", UserInfo)
store.commit('account/setRoutesConfig', UserInfo) // 将用户信息存入vuex
}
})
getPermission().then(result => { // 获取权限
if (result.data.data != null) {
const Permission = result.data.data.permission
console.log("Permission: ", Permission)
store.commit('account/setPermissions', Permission) // 将权限信息存入vuex
}
})
getRoutesConfig().then(result => { // 获取路由配置
if (result.data.data != null) {
const routesConfig = result.data.data
console.log("routesConfig: ", routesConfig)
store.commit('account/setRoutesConfig', routesConfig) // 将路由配置信息存入vuex
loadRoutes([routesConfig]) // 加载路由
}
})
getSettings().then(result => { // 获取系统配置
if (result.data.data != null) {
const settings = result.data.data
store.commit('account/setRoutesConfig', settings) // 将系统配置信息存入vuex
store.commit('account/setSettings', settings) // 将系统配置信息存入vuex
}
})
getCompany().then(result => { // 获取公司信息
if (result.data.data != null) {
const company = result.data.data
store.commit('account/setCompany', company) // 将公司信息存入vuex
}
})
getProject().then(result => { // 获取项目信息
if (result.data.data != null) {
const project = result.data.data
store.commit('account/setProject', project) // 将项目信息存入vuex
}
})
}
// -------------------------------- 以上为刷新页面时,重新加载路由 权限 用户信息的代码 --------------------------------

View File

@ -5,6 +5,8 @@ const BASE_URL = process.env.VUE_APP_API_BASE_URL // 获取环境变量VUE_APP_A
module.exports = {
BASE_URL,
PROJECT: `${BASE_URL}/AdminUser/v1/project`,
COMPANY: `${BASE_URL}/AdminUser/v1/company`,
LOGIN: `${BASE_URL}/AdminUser/v1/login`,
ROUTES: `${BASE_URL}/AdminUser/v1/routers`,
USERINFO: `${BASE_URL}/AdminUser/v1/userinfo`,

View File

@ -1,4 +1,4 @@
import {LOGIN, ROUTES, USERINFO,PERMISSION,SETTINGS} from '@/services/base/api'
import {LOGIN, ROUTES, USERINFO,PERMISSION,SETTINGS,PROJECT,COMPANY} from '@/services/base/api'
import {request, METHOD, removeAuthorization} from '@/utils/request'
/**
* 登录服务
@ -60,6 +60,30 @@ export async function getSettings() { // 获取用户设置
})
}
/**
* 获取项目信息
* @param beid
* @returns {Promise<AxiosResponse<Tuple>>}
*/
export async function getProject() { // 获取项目信息
return request(PROJECT, METHOD.POST, {
beid:parseInt(process.env.VUE_APP_BEID)
})
}
/**
* 获取公司信息
* @param company_id
* @returns {Promise<AxiosResponse<T>>}
*/
export async function getCompany() { // 获取公司信息
const userId = parseInt(localStorage.getItem(process.env.VUE_APP_UID_KEY)) // 获取用户id并转换为整数
return request(COMPANY, METHOD.POST, {
uid: userId
})
}
/**
* 退出登录
*/
@ -68,6 +92,8 @@ export function logout() {
localStorage.removeItem(process.env.VUE_APP_PERMISSIONS_KEY) // 删除权限配置
localStorage.removeItem(process.env.VUE_APP_USER_KEY) // 删除用户信息
localStorage.removeItem(process.env.VUE_APP_UID_KEY) // 删除用户id
localStorage.removeItem(process.env.VUE_APP_USER_SETTINGS_KEY) // 删除用户设置
localStorage.removeItem(process.env.VUE_APP_COMPANY_KEY) // 删除公司信息
removeAuthorization()
}
export default {
@ -76,5 +102,7 @@ export default {
getRoutesConfig,
getPermission,
getUserInfo,
getSettings
getSettings,
getProject,
getCompany,
}

View File

@ -2,10 +2,12 @@ export default {
namespaced: true,
state: {
uid: 0,
user: undefined, // 用户信息
permissions: undefined, // 权限
routesConfig: undefined, // 路由配置
settings: undefined // 用户配置
user: [], // 用户信息
permissions: [], // 权限
settings: [], // 用户配置
project: [], // 项目信息
company: [], // 公司信息
},
getters: {
uid: state => { // 用户id
@ -61,26 +63,57 @@ export default {
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则赋值为空对象
state.settings = state.settings ? state.settings : [] // 如果state.settings为null则赋值为空对象
} catch (e) { // 捕获异常
console.error(e.message)
}
}
return state.settings // 如果有用户配置,则返回用户配置
},
project: state => { // 项目信息
if (!state.project) { // 如果没有项目信息
try {
const project = localStorage.getItem(process.env.VUE_APP_PROJECT_KEY) // 获取项目信息
state.project = JSON.parse(project) // 将字符串转换为json对象
state.project = state.project ? state.project : [] // 如果state.project为null则赋值为空对象
} catch (e) { // 捕获异常
console.error(e.message)
}
}
},
company: state => { // 公司信息
if (!state.company) { // 如果没有公司信息
try {
const company = localStorage.getItem(process.env.VUE_APP_COMPANY_KEY) // 获取公司信息
state.company = JSON.parse(company) // 将字符串转换为json对象
state.company = state.company ? state.company : [] // 如果state.company为null则赋值为空对象
}
catch (e) { // 捕获异常
console.error(e.message)
}
}
},
},
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) { // 设置用户信息
state.user = user
if (JSON.stringify(user) === undefined){
user = []
}
localStorage.setItem(process.env.VUE_APP_USER_KEY, JSON.stringify(user))// 将所有用户信息存储到process.env.VUE_APP_USER_KEY中
},
setPermissions(state, permissions) { // 设置权限
state.permissions = permissions
if (JSON.stringify(permissions) === undefined){
permissions = []
}
localStorage.setItem(process.env.VUE_APP_PERMISSIONS_KEY, JSON.stringify(permissions)) // 将所有权限信息存储到process.env.VUE_APP_PERMISSIONS_KEY中
},
setRoutesConfig(state, routesConfig) { // 设置路由配置
@ -89,7 +122,25 @@ export default {
},
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中
if (JSON.stringify(settings) === undefined){
settings = []
}
localStorage.setItem(process.env.VUE_APP_USER_SETTINGS_KEY, JSON.stringify(settings)) // 将所有用户配置信息存储到process.env.VUE_APP_USER_SETTINGS_KEY中
},
setProject(state, project) { // 设置项目信息
state.project = project
if (JSON.stringify(project) === undefined){
project = []
}
localStorage.setItem(process.env.VUE_APP_PROJECT_KEY, JSON.stringify(project)) // 将所有项目信息存储到process.env.VUE_APP_PROJECT_KEY中
},
setCompany(state, company) { // 设置公司信息
state.company = company
if (JSON.stringify(company) === undefined){
company = []
}
localStorage.setItem(process.env.VUE_APP_COMPANY_KEY, JSON.stringify(company)) // 将所有公司信息存储到process.env.VUE_APP_COMPANY_KEY中
},
}
}

View File

@ -13,14 +13,18 @@
*/
function hasAuthority(to, permissions) { // 权限校验
// 循环 to.meta.authority.permission 集合
if (to.meta && to.meta.authority.permission.length > 0) {
if (to.meta.authority.permission){
if (to.meta.authority.permission.length > 0) {
for (let i = 0; i < to.meta.authority.permission.length; i++) {
// 判断用户权限集合中是否包含 to.meta.authority.permission 中的权限
if (permissions){
if (permissions.includes(to.meta.authority.permission[i])) {
return false
}
}
}
}
}
// 如果 to.meta.authority.permission 匹配到了 permissions 中的某个权限就返回false
return true // 如果都满足返回true
}
@ -35,7 +39,7 @@ function hasAuthority(to, permissions) { // 权限校验
function filterMenu(menuData, permissions, roles) { // 过滤菜单
return menuData.filter(menu => {
if (menu.meta && menu.meta.invisible === undefined) { // 如果菜单有meta属性并且没有invisible属性
if (!hasAuthority(menu, permissions, roles)) { // 如果没有权限
if (!hasAuthority(menu, permissions)) { // 如果没有权限
return false // 返回false
}
}

View File

@ -63,8 +63,10 @@ const reqCommon = { // 请求拦截器
const {url, xsrfCookieName} = config // 获取config中的url和xsrfCookieName
if (url.indexOf('login') === -1 && xsrfCookieName && !Cookie.get(xsrfCookieName)) {
// 如果url中不包含login并且xsrfCookieName存在并且Cookie中不存在xsrfCookieName
if (localStorage.getItem(process.env.VUE_APP_UID_KEY)) {
message.warning('认证 token 已过期,请重新登录') // 提示
}
}
return config
},
/**

View File

@ -33,7 +33,9 @@ const METHOD = {
* @returns {Promise<AxiosResponse<T>>}
*/
async function request(url, method, params, config) { // 请求方法
if (Cookie.get(xsrfHeaderName)) { // 检查cookie中是否存在认证信息
axios.defaults.headers.common[xsrfHeaderName] = Cookie.get(xsrfHeaderName)
}
switch (method) {
case METHOD.GET:
return axios.get(url, {params, ...config})
@ -165,6 +167,7 @@ function parseUrlParams(url) { // 解析 url 中的参数
export {
METHOD,
AUTH_TYPE,
xsrfHeaderName,
request,
setAuthorization,
removeAuthorization,

View File

@ -90,6 +90,7 @@ function parseRoutes(routesConfig, routerMap) { // 解析路由
// 根据权限过滤路由
function filterRoutesConfig(routes, permissions) {
const res = []
routes.forEach(route => {
const tmp = { ...route }
if (hasPermission(permissions, tmp)) {