使用Pinia代替Vuex进行数据存储

master
RuoYi 2 years ago
parent 6f359c1534
commit 44ad220cdd
  1. 6
      package.json
  2. 4
      src/components/HeaderSearch/index.vue
  3. 34
      src/components/SizeSelect/index.vue
  4. 21
      src/components/TopNav/index.vue
  5. 4
      src/directive/permission/hasPermi.js
  6. 4
      src/directive/permission/hasRole.js
  7. 8
      src/layout/components/AppMain.vue
  8. 22
      src/layout/components/Navbar.vue
  9. 52
      src/layout/components/Settings/index.vue
  10. 5
      src/layout/components/Sidebar/Logo.vue
  11. 17
      src/layout/components/Sidebar/index.vue
  12. 6
      src/layout/components/TagsView/ScrollPane.vue
  13. 16
      src/layout/components/TagsView/index.vue
  14. 27
      src/layout/index.vue
  15. 14
      src/permission.js
  16. 6
      src/plugins/auth.js
  17. 20
      src/plugins/tab.js
  18. 18
      src/store/getters.js
  19. 20
      src/store/index.js
  20. 103
      src/store/modules/app.js
  21. 87
      src/store/modules/permission.js
  22. 66
      src/store/modules/settings.js
  23. 354
      src/store/modules/tagsView.js
  24. 148
      src/store/modules/user.js
  25. 6
      src/utils/dynamicTitle.js
  26. 6
      src/utils/permission.js
  27. 4
      src/utils/request.js
  28. 5
      src/views/login.vue
  29. 9
      src/views/system/user/profile/userAvatar.vue
  30. 4
      vite/plugins/auto-import.js

@ -6,7 +6,7 @@
"license": "MIT",
"scripts": {
"dev": "vite",
"build:prod": "vite build",
"build:prod": "vite build",
"build:stage": "vite build --mode staging",
"preview": "vite preview"
},
@ -25,10 +25,10 @@
"js-cookie": "3.0.1",
"jsencrypt": "3.2.1",
"nprogress": "0.2.0",
"pinia": "2.0.14",
"vue": "3.2.31",
"vue-cropper": "1.0.3",
"vue-router": "4.0.14",
"vuex": "4.0.2"
"vue-router": "4.0.14"
},
"devDependencies": {
"@vitejs/plugin-vue": "2.3.3",

@ -21,6 +21,7 @@
import Fuse from 'fuse.js'
import { getNormalPath } from '@/utils/ruoyi'
import { isHttp } from '@/utils/validate'
import usePermissionStore from '@/store/modules/permission'
const search = ref('');
const options = ref([]);
@ -28,9 +29,8 @@ const searchPool = ref([]);
const show = ref(false);
const fuse = ref(undefined);
const headerSearchSelectRef = ref(null);
const store = useStore();
const router = useRouter();
const routes = computed(() => store.getters.permission_routes);
const routes = computed(() => usePermissionStore().routes);
function click() {
show.value = !show.value

@ -16,36 +16,24 @@
</template>
<script setup>
import { ElMessage } from 'element-plus'
import useAppStore from "@/store/modules/app";
const store = useStore();
const size = computed(() => store.getters.size);
const appStore = useAppStore();
const size = computed(() => appStore.size);
const route = useRoute();
const router = useRouter();
const {proxy} = getCurrentInstance();
const { proxy } = getCurrentInstance();
const sizeOptions = ref([
{ label: '较大', value: 'large' },
{ label: '默认', value: 'default' },
{ label: '稍小', value: 'small' },
])
{ label: "较大", value: "large" },
{ label: "默认", value: "default" },
{ label: "稍小", value: "small" },
]);
function refreshView() {
// In order to make the cached page re-rendered
store.dispatch('tagsView/delAllCachedViews', route)
const { fullPath } = route
nextTick(() => {
router.replace({
path: '/redirect' + fullPath
})
})
}
function handleSetSize(size) {
proxy.$modal.loading("正在设置布局大小,请稍候...");
store.dispatch('app/setSize', size)
setTimeout("window.location.reload()", 1000)
};
appStore.setSize(size);
setTimeout("window.location.reload()", 1000);
}
</script>
<style lang='scss' scoped>

@ -30,6 +30,9 @@
<script setup>
import { constantRoutes } from "@/router"
import { isHttp } from '@/utils/validate'
import useAppStore from '@/store/modules/app'
import useSettingsStore from '@/store/modules/settings'
import usePermissionStore from '@/store/modules/permission'
//
const visibleNumber = ref(null);
@ -38,14 +41,16 @@ const currentIndex = ref(null);
//
const hideList = ['/index', '/user/profile'];
const store = useStore();
const appStore = useAppStore()
const settingsStore = useSettingsStore()
const permissionStore = usePermissionStore()
const route = useRoute();
const router = useRouter();
//
const theme = computed(() => store.state.settings.theme);
const theme = computed(() => settingsStore.theme);
//
const routers = computed(() => store.state.permission.topbarRouters);
const routers = computed(() => permissionStore.topbarRouters);
//
const topMenus = computed(() => {
@ -91,10 +96,10 @@ const activeMenu = computed(() => {
if (path !== undefined && path.lastIndexOf("/") > 0 && hideList.indexOf(path) === -1) {
const tmpPath = path.substring(1, path.length);
activePath = "/" + tmpPath.substring(0, tmpPath.indexOf("/"));
store.dispatch('app/toggleSideBarHide', false);
appStore.toggleSideBarHide(false);
} else if(!route.children) {
activePath = path;
store.dispatch('app/toggleSideBarHide', true);
appStore.toggleSideBarHide(true);
}
activeRoutes(activePath);
return activePath;
@ -114,11 +119,11 @@ function handleSelect(key, keyPath) {
} else if (!route || !route.children) {
//
router.push({ path: key });
store.dispatch('app/toggleSideBarHide', true);
appStore.toggleSideBarHide(true);
} else {
//
activeRoutes(key);
store.dispatch('app/toggleSideBarHide', false);
appStore.toggleSideBarHide(false);
}
}
@ -132,7 +137,7 @@ function activeRoutes(key) {
});
}
if(routes.length > 0) {
store.commit("SET_SIDEBAR_ROUTERS", routes);
permissionStore.setSidebarRouters(routes);
}
return routes;
}

@ -3,13 +3,13 @@
* Copyright (c) 2019 ruoyi
*/
import store from '@/store'
import useUserStore from '@/store/modules/user'
export default {
mounted(el, binding, vnode) {
const { value } = binding
const all_permission = "*:*:*";
const permissions = store.getters && store.getters.permissions
const permissions = useUserStore().permissions
if (value && value instanceof Array && value.length > 0) {
const permissionFlag = value

@ -3,13 +3,13 @@
* Copyright (c) 2019 ruoyi
*/
import store from '@/store'
import useUserStore from '@/store/modules/user'
export default {
mounted(el, binding, vnode) {
const { value } = binding
const super_admin = "admin";
const roles = store.getters && store.getters.roles
const roles = useUserStore().roles
if (value && value instanceof Array && value.length > 0) {
const roleFlag = value

@ -11,11 +11,13 @@
</template>
<script setup>
let store = useStore()
import useTagsViewStore from '@/store/modules/tagsview'
const tagsViewStore = useTagsViewStore()
const route = useRoute()
store.dispatch('tagsView/addCachedView', route)
tagsViewStore.addCachedView(route)
const cachedViews = computed(() => {
return store.state.tagsView.cachedViews
return tagsViewStore.cachedViews
})
</script>

@ -1,11 +1,11 @@
<template>
<div class="navbar">
<hamburger id="hamburger-container" :is-active="getters.sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
<breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!$store.state.settings.topNav" />
<top-nav id="topmenu-container" class="topmenu-container" v-if="$store.state.settings.topNav" />
<hamburger id="hamburger-container" :is-active="appStore.sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
<breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!settingsStore.topNav" />
<top-nav id="topmenu-container" class="topmenu-container" v-if="settingsStore.topNav" />
<div class="right-menu">
<template v-if="getters.device !== 'mobile'">
<template v-if="appStore.device !== 'mobile'">
<header-search id="header-search" class="right-menu-item" />
<el-tooltip content="源码地址" effect="dark" placement="bottom">
@ -25,7 +25,7 @@
<div class="avatar-container">
<el-dropdown @command="handleCommand" class="right-menu-item hover-effect" trigger="click">
<div class="avatar-wrapper">
<img :src="getters.avatar" class="user-avatar" />
<img :src="userStore.avatar" class="user-avatar" />
<el-icon><caret-bottom /></el-icon>
</div>
<template #dropdown>
@ -57,12 +57,16 @@ import SizeSelect from '@/components/SizeSelect'
import HeaderSearch from '@/components/HeaderSearch'
import RuoYiGit from '@/components/RuoYi/Git'
import RuoYiDoc from '@/components/RuoYi/Doc'
import useAppStore from '@/store/modules/app'
import useUserStore from '@/store/modules/user'
import useSettingsStore from '@/store/modules/settings'
const store = useStore();
const getters = computed(() => store.getters);
const appStore = useAppStore()
const userStore = useUserStore()
const settingsStore = useSettingsStore()
function toggleSideBar() {
store.dispatch('app/toggleSideBar')
appStore.toggleSideBar()
}
function handleCommand(command) {
@ -84,7 +88,7 @@ function logout() {
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
store.dispatch('LogOut').then(() => {
userStore.logOut().then(() => {
location.href = '/index';
})
}).catch(() => { });

@ -84,26 +84,28 @@ import originElementPlus from 'element-plus/theme-chalk/index.css'
import axios from 'axios'
import { ElLoading, ElMessage } from 'element-plus'
import { useDynamicTitle } from '@/utils/dynamicTitle'
import useAppStore from '@/store/modules/app'
import useSettingsStore from '@/store/modules/settings'
import usePermissionStore from '@/store/modules/permission'
const { proxy } = getCurrentInstance();
const store = useStore();
const appStore = useAppStore()
const settingsStore = useSettingsStore()
const permissionStore = usePermissionStore()
const showSettings = ref(false);
const theme = ref(store.state.settings.theme);
const sideTheme = ref(store.state.settings.sideTheme);
const storeSettings = computed(() => store.state.settings);
const theme = ref(settingsStore.theme);
const sideTheme = ref(settingsStore.sideTheme);
const storeSettings = computed(() => settingsStore);
const predefineColors = ref(["#409EFF", "#ff4500", "#ff8c00", "#ffd700", "#90ee90", "#00ced1", "#1e90ff", "#c71585"]);
/** 是否需要topnav */
const topNav = computed({
get: () => storeSettings.value.topNav,
set: (val) => {
store.dispatch('settings/changeSetting', {
key: 'topNav',
value: val
})
settingsStore.changeSetting({ key: 'topNav', value: val })
if (!val) {
store.dispatch('app/toggleSideBarHide', false);
store.commit("SET_SIDEBAR_ROUTERS", store.state.permission.defaultRoutes);
appStore.toggleSideBarHide(false);
permissionStore.setSidebarRouters(permissionStore.defaultRoutes);
}
}
})
@ -111,57 +113,39 @@ const topNav = computed({
const tagsView = computed({
get: () => storeSettings.value.tagsView,
set: (val) => {
store.dispatch('settings/changeSetting', {
key: 'tagsView',
value: val
})
settingsStore.changeSetting({ key: 'tagsView', value: val })
}
})
/**是否需要固定头部 */
const fixedHeader = computed({
get: () => storeSettings.value.fixedHeader,
set: (val) => {
store.dispatch('settings/changeSetting', {
key: 'fixedHeader',
value: val
})
settingsStore.changeSetting({ key: 'fixedHeader', value: val })
}
})
/**是否需要侧边栏的logo */
const sidebarLogo = computed({
get: () => storeSettings.value.sidebarLogo,
set: (val) => {
store.dispatch('settings/changeSetting', {
key: 'sidebarLogo',
value: val
})
settingsStore.changeSetting({ key: 'sidebarLogo', value: val })
}
})
/**是否需要侧边栏的动态网页的title */
const dynamicTitle = computed({
get: () => storeSettings.value.dynamicTitle,
set: (val) => {
store.dispatch('settings/changeSetting', {
key: 'dynamicTitle',
value: val
})
settingsStore.changeSetting({ key: 'dynamicTitle', value: val })
//
useDynamicTitle()
}
})
function themeChange(val) {
store.dispatch('settings/changeSetting', {
key: 'theme',
value: val
})
settingsStore.changeSetting({ key: 'theme', value: val })
theme.value = val;
}
function handleTheme(val) {
store.dispatch('settings/changeSetting', {
key: 'sideTheme',
value: val
})
settingsStore.changeSetting({ key: 'sideTheme', value: val })
sideTheme.value = val;
}
function saveSetting() {

@ -16,6 +16,7 @@
<script setup>
import variables from '@/assets/styles/variables.module.scss'
import logo from '@/assets/logo/logo.png'
import useSettingsStore from '@/store/modules/settings'
defineProps({
collapse: {
@ -25,8 +26,8 @@ defineProps({
})
const title = ref('若依管理系统');
const store = useStore();
const sideTheme = computed(() => store.state.settings.sideTheme);
const settingsStore = useSettingsStore();
const sideTheme = computed(() => settingsStore.sideTheme);
</script>
<style lang="scss" scoped>

@ -27,15 +27,20 @@
import Logo from './Logo'
import SidebarItem from './SidebarItem'
import variables from '@/assets/styles/variables.module.scss'
import useAppStore from '@/store/modules/app'
import useSettingsStore from '@/store/modules/settings'
import usePermissionStore from '@/store/modules/permission'
const route = useRoute();
const store = useStore();
const appStore = useAppStore()
const settingsStore = useSettingsStore()
const permissionStore = usePermissionStore()
const sidebarRouters = computed(() => store.getters.sidebarRouters);
const showLogo = computed(() => store.state.settings.sidebarLogo);
const sideTheme = computed(() => store.state.settings.sideTheme);
const theme = computed(() => store.state.settings.theme);
const isCollapse = computed(() => !store.state.app.sidebar.opened);
const sidebarRouters = computed(() => permissionStore.sidebarRouters);
const showLogo = computed(() => settingsStore.sidebarLogo);
const sideTheme = computed(() => settingsStore.sideTheme);
const theme = computed(() => settingsStore.theme);
const isCollapse = computed(() => !appStore.sidebar.opened);
const activeMenu = computed(() => {
const { meta, path } = route;

@ -10,6 +10,8 @@
</template>
<script setup>
import useTagsViewStore from '@/store/modules/tagsview'
const tagAndTagSpacing = ref(4);
const { proxy } = getCurrentInstance();
@ -32,8 +34,8 @@ const emitScroll = () => {
emits('scroll')
}
const store = useStore();
const visitedViews = computed(() => store.state.tagsView.visitedViews);
const tagsViewStore = useTagsViewStore()
const visitedViews = computed(() => tagsViewStore.visitedViews);
function moveToTarget(currentTag) {
const $container = proxy.$refs.scrollContainer.$el

@ -44,6 +44,9 @@
<script setup>
import ScrollPane from './ScrollPane'
import { getNormalPath } from '@/utils/ruoyi'
import useTagsViewStore from '@/store/modules/tagsview'
import useSettingsStore from '@/store/modules/settings'
import usePermissionStore from '@/store/modules/permission'
const visible = ref(false);
const top = ref(0);
@ -53,13 +56,12 @@ const affixTags = ref([]);
const scrollPaneRef = ref(null);
const { proxy } = getCurrentInstance();
const store = useStore();
const route = useRoute();
const router = useRouter();
const visitedViews = computed(() => store.state.tagsView.visitedViews);
const routes = computed(() => store.state.permission.routes);
const theme = computed(() => store.state.settings.theme);
const visitedViews = computed(() => useTagsViewStore().visitedViews);
const routes = computed(() => usePermissionStore().routes);
const theme = computed(() => useSettingsStore().theme);
watch(route, () => {
addTags()
@ -131,14 +133,14 @@ function initTags() {
for (const tag of res) {
// Must have tag name
if (tag.name) {
store.dispatch('tagsView/addVisitedView', tag)
useTagsViewStore().addVisitedView(tag)
}
}
}
function addTags() {
const { name } = route
if (name) {
store.dispatch('tagsView/addView', route)
useTagsViewStore().addView(route)
}
return false
}
@ -149,7 +151,7 @@ function moveToCurrentTag() {
scrollPaneRef.value.moveToTarget(r);
// when query is different then update
if (r.fullPath !== route.fullPath) {
store.dispatch('tagsView/updateVisitedView', route)
useTagsViewStore().updateVisitedView(route)
}
}
}

@ -19,13 +19,16 @@ import Sidebar from './components/Sidebar/index.vue'
import { AppMain, Navbar, Settings, TagsView } from './components'
import defaultSettings from '@/settings'
const store = useStore();
const theme = computed(() => store.state.settings.theme);
const sideTheme = computed(() => store.state.settings.sideTheme);
const sidebar = computed(() => store.state.app.sidebar);
const device = computed(() => store.state.app.device);
const needTagsView = computed(() => store.state.settings.tagsView);
const fixedHeader = computed(() => store.state.settings.fixedHeader);
import useAppStore from '@/store/modules/app'
import useSettingsStore from '@/store/modules/settings'
const settingsStore = useSettingsStore()
const theme = computed(() => settingsStore.theme);
const sideTheme = computed(() => settingsStore.sideTheme);
const sidebar = computed(() => useAppStore().sidebar);
const device = computed(() => useAppStore().device);
const needTagsView = computed(() => settingsStore.tagsView);
const fixedHeader = computed(() => settingsStore.fixedHeader);
const classObj = computed(() => ({
hideSidebar: !sidebar.value.opened,
@ -39,18 +42,18 @@ const WIDTH = 992; // refer to Bootstrap's responsive design
watchEffect(() => {
if (device.value === 'mobile' && sidebar.value.opened) {
store.dispatch('app/closeSideBar', { withoutAnimation: false })
useAppStore().closeSideBar({ withoutAnimation: false })
}
if (width.value - 1 < WIDTH) {
store.dispatch('app/toggleDevice', 'mobile')
store.dispatch('app/closeSideBar', { withoutAnimation: true })
useAppStore().toggleDevice('mobile')
useAppStore().closeSideBar({ withoutAnimation: true })
} else {
store.dispatch('app/toggleDevice', 'desktop')
useAppStore().toggleDevice('desktop')
}
})
function handleClickOutside() {
store.dispatch('app/closeSideBar', { withoutAnimation: false })
useAppStore().closeSideBar({ withoutAnimation: false })
}
const settingRef = ref(null);

@ -1,11 +1,13 @@
import router from './router'
import store from './store'
import { ElMessage } from 'element-plus'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { getToken } from '@/utils/auth'
import { isHttp } from '@/utils/validate'
import { isRelogin } from '@/utils/request'
import useUserStore from '@/store/modules/user'
import useSettingsStore from '@/store/modules/settings'
import usePermissionStore from '@/store/modules/permission'
NProgress.configure({ showSpinner: false });
@ -14,18 +16,18 @@ const whiteList = ['/login', '/auth-redirect', '/bind', '/register'];
router.beforeEach((to, from, next) => {
NProgress.start()
if (getToken()) {
to.meta.title && store.dispatch('settings/setTitle', to.meta.title)
to.meta.title && useSettingsStore().setTitle(to.meta.title)
/* has token*/
if (to.path === '/login') {
next({ path: '/' })
NProgress.done()
} else {
if (store.getters.roles.length === 0) {
if (useUserStore().roles.length === 0) {
isRelogin.show = true
// 判断当前用户是否已拉取完user_info信息
store.dispatch('GetInfo').then(() => {
useUserStore().getInfo().then(() => {
isRelogin.show = false
store.dispatch('GenerateRoutes').then(accessRoutes => {
usePermissionStore().generateRoutes().then(accessRoutes => {
// 根据roles权限生成可访问的路由表
accessRoutes.forEach(route => {
if (!isHttp(route.path)) {
@ -35,7 +37,7 @@ router.beforeEach((to, from, next) => {
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
})
}).catch(err => {
store.dispatch('LogOut').then(() => {
useUserStore().logOut().then(() => {
ElMessage.error(err)
next({ path: '/' })
})

@ -1,8 +1,8 @@
import store from '@/store'
import useUserStore from '@/store/modules/user'
function authPermission(permission) {
const all_permission = "*:*:*";
const permissions = store.getters && store.getters.permissions
const permissions = useUserStore().permissions
if (permission && permission.length > 0) {
return permissions.some(v => {
return all_permission === v || v === permission
@ -14,7 +14,7 @@ function authPermission(permission) {
function authRole(role) {
const super_admin = "admin";
const roles = store.getters && store.getters.roles
const roles = useUserStore().roles
if (role && role.length > 0) {
return roles.some(v => {
return super_admin === v || v === role

@ -1,4 +1,4 @@
import store from '@/store'
import useTagsViewStore from '@/store/modules/tagsview'
import router from '@/router'
export default {
@ -14,7 +14,7 @@ export default {
}
});
}
return store.dispatch('tagsView/delCachedView', obj).then(() => {
return useTagsViewStore().delCachedView(obj).then(() => {
const { path, query } = obj
router.replace({
path: '/redirect' + path,
@ -24,7 +24,7 @@ export default {
},
// 关闭当前tab页签打开新页签
closeOpenPage(obj) {
store.dispatch("tagsView/delView", router.currentRoute.value);
useTagsViewStore().delView(router.currentRoute.value);
if (obj !== undefined) {
return router.push(obj);
}
@ -32,27 +32,27 @@ export default {
// 关闭指定tab页签
closePage(obj) {
if (obj === undefined) {
return store.dispatch('tagsView/delView', router.currentRoute.value).then(({ lastPath }) => {
return useTagsViewStore().delView(router.currentRoute.value).then(({ lastPath }) => {
return router.push(lastPath || '/index');
});
}
return store.dispatch('tagsView/delView', obj);
return useTagsViewStore().delView(obj);
},
// 关闭所有tab页签
closeAllPage() {
return store.dispatch('tagsView/delAllViews');
return useTagsViewStore().delAllViews();
},
// 关闭左侧tab页签
closeLeftPage(obj) {
return store.dispatch('tagsView/delLeftTags', obj || router.currentRoute.value);
return useTagsViewStore().delLeftTags(obj || router.currentRoute.value);
},
// 关闭右侧tab页签
closeRightPage(obj) {
return store.dispatch('tagsView/delRightTags', obj || router.currentRoute.value);
return useTagsViewStore().delRightTags(obj || router.currentRoute.value);
},
// 关闭其他tab页签
closeOtherPage(obj) {
return store.dispatch('tagsView/delOthersViews', obj || router.currentRoute.value);
return useTagsViewStore().delOthersViews(obj || router.currentRoute.value);
},
// 打开tab页签
openPage(url) {
@ -60,6 +60,6 @@ export default {
},
// 修改tab页签
updatePage(obj) {
return store.dispatch('tagsView/updateVisitedView', obj);
return useTagsViewStore().updateVisitedView(obj);
}
}

@ -1,18 +0,0 @@
const getters = {
sidebar: state => state.app.sidebar,
size: state => state.app.size,
device: state => state.app.device,
visitedViews: state => state.tagsView.visitedViews,
cachedViews: state => state.tagsView.cachedViews,
token: state => state.user.token,
avatar: state => state.user.avatar,
name: state => state.user.name,
introduction: state => state.user.introduction,
roles: state => state.user.roles,
permissions: state => state.user.permissions,
permission_routes: state => state.permission.routes,
topbarRouters:state => state.permission.topbarRouters,
defaultRoutes:state => state.permission.defaultRoutes,
sidebarRouters:state => state.permission.sidebarRouters,
}
export default getters

@ -1,21 +1,3 @@
import { createStore } from 'vuex'
import app from './modules/app'
import user from './modules/user'
import tagsView from './modules/tagsView'
import permission from './modules/permission'
import settings from './modules/settings'
import getters from './getters'
const store = createStore({
modules: {
app,
user,
tagsView,
permission,
settings
},
getters
});
const store = createPinia()
export default store

@ -1,66 +1,47 @@
import Cookies from 'js-cookie'
const state = {
sidebar: {
opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true,
withoutAnimation: false,
hide: false
},
device: 'desktop',
size: Cookies.get('size') || 'default'
}
const mutations = {
TOGGLE_SIDEBAR: state => {
if (state.sidebar.hide) {
return false;
const useAppStore = defineStore(
'app',
{
state: () => ({
sidebar: {
opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true,
withoutAnimation: false,
hide: false
},
device: 'desktop',
size: Cookies.get('size') || 'default'
}),
actions: {
toggleSideBar(withoutAnimation) {
if (this.sidebar.hide) {
return false;
}
this.sidebar.opened = !this.sidebar.opened
this.sidebar.withoutAnimation = withoutAnimation
if (this.sidebar.opened) {
Cookies.set('sidebarStatus', 1)
} else {
Cookies.set('sidebarStatus', 0)
}
},
closeSideBar(withoutAnimation) {
Cookies.set('sidebarStatus', 0)
this.sidebar.opened = false
this.sidebar.withoutAnimation = withoutAnimation
},
toggleDevice(device) {
this.device = device
},
setSize(size) {
this.size = size;
Cookies.set('size', size)
},
toggleSideBarHide(status) {
this.sidebar.hide = status
}
}
state.sidebar.opened = !state.sidebar.opened
state.sidebar.withoutAnimation = false
if (state.sidebar.opened) {
Cookies.set('sidebarStatus', 1)
} else {
Cookies.set('sidebarStatus', 0)
}
},
CLOSE_SIDEBAR: (state, withoutAnimation) => {
Cookies.set('sidebarStatus', 0)
state.sidebar.opened = false
state.sidebar.withoutAnimation = withoutAnimation
},
TOGGLE_DEVICE: (state, device) => {
state.device = device
},
SET_SIZE: (state, size) => {
state.size = size
Cookies.set('size', size)
},
SET_SIDEBAR_HIDE: (state, status) => {
state.sidebar.hide = status
}
}
const actions = {
toggleSideBar({ commit }) {
commit('TOGGLE_SIDEBAR')
},
closeSideBar({ commit }, { withoutAnimation }) {
commit('CLOSE_SIDEBAR', withoutAnimation)
},
toggleDevice({ commit }, device) {
commit('TOGGLE_DEVICE', device)
},
setSize({ commit }, size) {
commit('SET_SIZE', size)
},
toggleSideBarHide({ commit }, status) {
commit('SET_SIDEBAR_HIDE', status)
}
}
})
export default {
namespaced: true,
state,
mutations,
actions
}
export default useAppStore

@ -7,51 +7,50 @@ import InnerLink from '@/layout/components/InnerLink'
// 匹配views里面所有的.vue文件
const modules = import.meta.glob('./../../views/**/*.vue')
const permission = {
state: {
routes: [],
addRoutes: [],
defaultRoutes: [],
topbarRouters: [],
sidebarRouters: []
},
mutations: {
SET_ROUTES: (state, routes) => {
state.addRoutes = routes
state.routes = constantRoutes.concat(routes)
},
SET_DEFAULT_ROUTES: (state, routes) => {
state.defaultRoutes = constantRoutes.concat(routes)
},
SET_TOPBAR_ROUTES: (state, routes) => {
state.topbarRouters = routes
},
SET_SIDEBAR_ROUTERS: (state, routes) => {
state.sidebarRouters = routes
},
},
actions: {
// 生成路由
GenerateRoutes({ commit }) {
return new Promise(resolve => {
// 向后端请求路由数据
getRouters().then(res => {
const sdata = JSON.parse(JSON.stringify(res.data))
const rdata = JSON.parse(JSON.stringify(res.data))
const defaultData = JSON.parse(JSON.stringify(res.data))
const sidebarRoutes = filterAsyncRouter(sdata)
const rewriteRoutes = filterAsyncRouter(rdata, false, true)
const defaultRoutes = filterAsyncRouter(defaultData)
commit('SET_ROUTES', rewriteRoutes)
commit('SET_SIDEBAR_ROUTERS', constantRoutes.concat(sidebarRoutes))
commit('SET_DEFAULT_ROUTES', sidebarRoutes)
commit('SET_TOPBAR_ROUTES', defaultRoutes)
resolve(rewriteRoutes)
const usePermissionStore = defineStore(
'permission',
{
state: () => ({
routes: [],
addRoutes: [],
defaultRoutes: [],
topbarRouters: [],
sidebarRouters: []
}),
actions: {
setRoutes(routes) {
this.addRoutes = routes
this.routes = constantRoutes.concat(routes)
},
setDefaultRoutes(routes) {
this.defaultRoutes = constantRoutes.concat(routes)
},
setTopbarRoutes(routes) {
this.topbarRouters = routes
},
setSidebarRouters(routes) {
this.sidebarRouters = routes
},
generateRoutes(roles) {
return new Promise(resolve => {
// 向后端请求路由数据
getRouters().then(res => {
const sdata = JSON.parse(JSON.stringify(res.data))
const rdata = JSON.parse(JSON.stringify(res.data))
const defaultData = JSON.parse(JSON.stringify(res.data))
const sidebarRoutes = filterAsyncRouter(sdata)
const rewriteRoutes = filterAsyncRouter(rdata, false, true)
const defaultRoutes = filterAsyncRouter(defaultData)
this.setRoutes(rewriteRoutes)
this.setSidebarRouters(constantRoutes.concat(sidebarRoutes))
this.setDefaultRoutes(sidebarRoutes)
this.setTopbarRoutes(defaultRoutes)
resolve(rewriteRoutes)
})
})
})
}
}
}
}
})
// 遍历后台传来的路由字符串,转换为组件对象
function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) {
@ -116,4 +115,4 @@ export const loadView = (view) => {
return res;
}
export default permission
export default usePermissionStore

@ -4,41 +4,35 @@ import { useDynamicTitle } from '@/utils/dynamicTitle'
const { sideTheme, showSettings, topNav, tagsView, fixedHeader, sidebarLogo, dynamicTitle } = defaultSettings
const storageSetting = JSON.parse(localStorage.getItem('layout-setting')) || ''
const state = {
title: '',
theme: storageSetting.theme || '#409EFF',
sideTheme: storageSetting.sideTheme || sideTheme,
showSettings: showSettings,
topNav: storageSetting.topNav === undefined ? topNav : storageSetting.topNav,
tagsView: storageSetting.tagsView === undefined ? tagsView : storageSetting.tagsView,
fixedHeader: storageSetting.fixedHeader === undefined ? fixedHeader : storageSetting.fixedHeader,
sidebarLogo: storageSetting.sidebarLogo === undefined ? sidebarLogo : storageSetting.sidebarLogo,
dynamicTitle: storageSetting.dynamicTitle === undefined ? dynamicTitle : storageSetting.dynamicTitle
}
const mutations = {
CHANGE_SETTING: (state, { key, value }) => {
if (state.hasOwnProperty(key)) {
state[key] = value
}
}
}
const actions = {
// 修改布局设置
changeSetting({ commit }, data) {
commit('CHANGE_SETTING', data)
},
// 设置网页标题
setTitle({ commit }, title) {
state.title = title
useDynamicTitle();
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
const useSettingsStore = defineStore(
'settings',
{
state: () => ({
title: '',
theme: storageSetting.theme || '#409EFF',
sideTheme: storageSetting.sideTheme || sideTheme,
showSettings: showSettings,
topNav: storageSetting.topNav === undefined ? topNav : storageSetting.topNav,
tagsView: storageSetting.tagsView === undefined ? tagsView : storageSetting.tagsView,
fixedHeader: storageSetting.fixedHeader === undefined ? fixedHeader : storageSetting.fixedHeader,
sidebarLogo: storageSetting.sidebarLogo === undefined ? sidebarLogo : storageSetting.sidebarLogo,
dynamicTitle: storageSetting.dynamicTitle === undefined ? dynamicTitle : storageSetting.dynamicTitle
}),
actions: {
// 修改布局设置
changeSetting(data) {
const { key, value } = data
if (this.hasOwnProperty(key)) {
this[key] = value
}
},
// 设置网页标题
setTitle(title) {
this.title = title
useDynamicTitle();
}
}
})
export default useSettingsStore

@ -1,207 +1,153 @@
const state = {
visitedViews: [],
cachedViews: []
}
const mutations = {
ADD_VISITED_VIEW: (state, view) => {
if (state.visitedViews.some(v => v.path === view.path)) return
state.visitedViews.push(
Object.assign({}, view, {
title: view.meta.title || 'no-name'
})
)
},
ADD_CACHED_VIEW: (state, view) => {
if (state.cachedViews.includes(view.name)) return
if (!view.meta.noCache) {
state.cachedViews.push(view.name)
}
},
DEL_VISITED_VIEW: (state, view) => {
for (const [i, v] of state.visitedViews.entries()) {
if (v.path === view.path) {
state.visitedViews.splice(i, 1)
break
}
}
},
DEL_CACHED_VIEW: (state, view) => {
const index = state.cachedViews.indexOf(view.name)
index > -1 && state.cachedViews.splice(index, 1)
},
DEL_OTHERS_VISITED_VIEWS: (state, view) => {
state.visitedViews = state.visitedViews.filter(v => {
return v.meta.affix || v.path === view.path
})
},
DEL_OTHERS_CACHED_VIEWS: (state, view) => {
const index = state.cachedViews.indexOf(view.name)
if (index > -1) {
state.cachedViews = state.cachedViews.slice(index, index + 1)
} else {
state.cachedViews = []
}
},
DEL_ALL_VISITED_VIEWS: state => {
// keep affix tags
const affixTags = state.visitedViews.filter(tag => tag.meta.affix)
state.visitedViews = affixTags
},
DEL_ALL_CACHED_VIEWS: state => {
state.cachedViews = []
},
UPDATE_VISITED_VIEW: (state, view) => {
for (let v of state.visitedViews) {
if (v.path === view.path) {
v = Object.assign(v, view)
break
const useTagsViewStore = defineStore(
'tags-view',
{
state: () => ({
visitedViews: [],
cachedViews: []
}),
actions: {
addView(view) {
this.addVisitedView(view)
this.addCachedView(view)
},
addVisitedView(view) {
if (this.visitedViews.some(v => v.path === view.path)) return
this.visitedViews.push(
Object.assign({}, view, {
title: view.meta.title || 'no-name'
})
)
},
addCachedView(view) {
if (this.cachedViews.includes(view.name)) return
if (!view.meta.noCache) {
this.cachedViews.push(view.name)
}
},
delView(view) {
return new Promise(resolve => {
this.delVisitedView(view)
this.delCachedView(view)
resolve({
visitedViews: [...this.visitedViews],
cachedViews: [...this.cachedViews]
})
})
},
delVisitedView(view) {
return new Promise(resolve => {
for (const [i, v] of this.visitedViews.entries()) {
if (v.path === view.path) {
this.visitedViews.splice(i, 1)
break
}
}
resolve([...this.visitedViews])
})
},
delCachedView(view) {
return new Promise(resolve => {
const index = this.cachedViews.indexOf(view.name)
index > -1 && this.cachedViews.splice(index, 1)
resolve([...this.cachedViews])
})
},
delOthersViews(view) {
return new Promise(resolve => {
this.delOthersVisitedViews(view)
this.delOthersCachedViews(view)
resolve({
visitedViews: [...this.visitedViews],
cachedViews: [...this.cachedViews]
})
})
},
delOthersVisitedViews(view) {
return new Promise(resolve => {
this.visitedViews = this.visitedViews.filter(v => {
return v.meta.affix || v.path === view.path
})
resolve([...this.visitedViews])
})
},
delOthersCachedViews(view) {
return new Promise(resolve => {
const index = this.cachedViews.indexOf(view.name)
if (index > -1) {
this.cachedViews = this.cachedViews.slice(index, index + 1)
} else {
this.cachedViews = []
}
resolve([...this.cachedViews])
})
},
delAllViews(view) {
return new Promise(resolve => {
this.delAllVisitedViews(view)
this.delAllCachedViews(view)
resolve({
visitedViews: [...this.visitedViews],
cachedViews: [...this.cachedViews]
})
})
},
delAllVisitedViews(view) {
return new Promise(resolve => {
const affixTags = this.visitedViews.filter(tag => tag.meta.affix)
this.visitedViews = affixTags
resolve([...this.visitedViews])
})
},
delAllCachedViews(view) {
return new Promise(resolve => {
this.cachedViews = []
resolve([...this.cachedViews])
})
},
updateVisitedView(view) {
for (let v of this.visitedViews) {
if (v.path === view.path) {
v = Object.assign(v, view)
break
}
}
},
delRightTags(view) {
return new Promise(resolve => {
const index = this.visitedViews.findIndex(v => v.path === view.path)
if (index === -1) {
return
}
this.visitedViews = this.visitedViews.filter((item, idx) => {
if (idx <= index || (item.meta && item.meta.affix)) {
return true
}
const i = this.cachedViews.indexOf(item.name)
if (i > -1) {
this.cachedViews.splice(i, 1)
}
return false
})
resolve([...this.visitedViews])
})
},
delLeftTags(view) {
const index = this.visitedViews.findIndex(v => v.path === view.path)
if (index === -1) {
return
}
this.visitedViews = this.visitedViews.filter((item, idx) => {
if (idx >= index || (item.meta && item.meta.affix)) {
return true
}
const i = this.cachedViews.indexOf(item.name)
if (i > -1) {
this.cachedViews.splice(i, 1)
}
return false
})
}
}
},
DEL_RIGHT_VIEWS: (state, view) => {
const index = state.visitedViews.findIndex(v => v.path === view.path)
if (index === -1) {
return
}
state.visitedViews = state.visitedViews.filter((item, idx) => {
if (idx <= index || (item.meta && item.meta.affix)) {
return true
}
const i = state.cachedViews.indexOf(item.name)
if (i > -1) {
state.cachedViews.splice(i, 1)
}
return false
})
},
DEL_LEFT_VIEWS: (state, view) => {
const index = state.visitedViews.findIndex(v => v.path === view.path)
if (index === -1) {
return
}
state.visitedViews = state.visitedViews.filter((item, idx) => {
if (idx >= index || (item.meta && item.meta.affix)) {
return true
}
const i = state.cachedViews.indexOf(item.name)
if (i > -1) {
state.cachedViews.splice(i, 1)
}
return false
})
}
}
const actions = {
addView({ dispatch }, view) {
dispatch('addVisitedView', view)
dispatch('addCachedView', view)
},
addVisitedView({ commit }, view) {
commit('ADD_VISITED_VIEW', view)
},
addCachedView({ commit }, view) {
commit('ADD_CACHED_VIEW', view)
},
delView({ dispatch, state }, view) {
return new Promise(resolve => {
dispatch('delVisitedView', view)
dispatch('delCachedView', view)
resolve({
visitedViews: [...state.visitedViews],
cachedViews: [...state.cachedViews]
})
})
},
delVisitedView({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_VISITED_VIEW', view)
resolve([...state.visitedViews])
})
},
delCachedView({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_CACHED_VIEW', view)
resolve([...state.cachedViews])
})
},
delOthersViews({ dispatch, state }, view) {
return new Promise(resolve => {
dispatch('delOthersVisitedViews', view)
dispatch('delOthersCachedViews', view)
resolve({
visitedViews: [...state.visitedViews],
cachedViews: [...state.cachedViews]
})
})
},
delOthersVisitedViews({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_OTHERS_VISITED_VIEWS', view)
resolve([...state.visitedViews])
})
},
delOthersCachedViews({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_OTHERS_CACHED_VIEWS', view)
resolve([...state.cachedViews])
})
},
delAllViews({ dispatch, state }, view) {
return new Promise(resolve => {
dispatch('delAllVisitedViews', view)
dispatch('delAllCachedViews', view)
resolve({
visitedViews: [...state.visitedViews],
cachedViews: [...state.cachedViews]
})
})
},
delAllVisitedViews({ commit, state }) {
return new Promise(resolve => {
commit('DEL_ALL_VISITED_VIEWS')
resolve([...state.visitedViews])
})
},
delAllCachedViews({ commit, state }) {
return new Promise(resolve => {
commit('DEL_ALL_CACHED_VIEWS')
resolve([...state.cachedViews])
})
},
updateVisitedView({ commit }, view) {
commit('UPDATE_VISITED_VIEW', view)
},
delRightTags({ commit }, view) {
return new Promise(resolve => {
commit('DEL_RIGHT_VIEWS', view)
resolve([...state.visitedViews])
})
},
delLeftTags({ commit }, view) {
return new Promise(resolve => {
commit('DEL_LEFT_VIEWS', view)
resolve([...state.visitedViews])
})
},
}
})
export default {
namespaced: true,
state,
mutations,
actions
}
export default useTagsViewStore

@ -2,97 +2,69 @@ import { login, logout, getInfo } from '@/api/login'
import { getToken, setToken, removeToken } from '@/utils/auth'
import defAva from '@/assets/images/profile.jpg'
const user = {
state: {
token: getToken(),
name: '',
avatar: '',
roles: [],
permissions: []
},
mutations: {
SET_TOKEN: (state, token) => {
state.token = token
},
SET_NAME: (state, name) => {
state.name = name
},
SET_AVATAR: (state, avatar) => {
state.avatar = avatar
},
SET_ROLES: (state, roles) => {
state.roles = roles
},
SET_PERMISSIONS: (state, permissions) => {
state.permissions = permissions
}
},
actions: {
// 登录
Login({ commit }, userInfo) {
const username = userInfo.username.trim()
const password = userInfo.password
const code = userInfo.code
const uuid = userInfo.uuid
return new Promise((resolve, reject) => {
login(username, password, code, uuid).then(res => {
setToken(res.token)
commit('SET_TOKEN', res.token)
resolve()
}).catch(error => {
reject(error)
const useUserStore = defineStore(
'user',
{
state: () => ({
token: getToken(),
name: '',
avatar: '',
roles: [],
permissions: []
}),
actions: {
// 登录
login(userInfo) {
const username = userInfo.username.trim()
const password = userInfo.password
const code = userInfo.code
const uuid = userInfo.uuid
return new Promise((resolve, reject) => {
login(username, password, code, uuid).then(res => {
setToken(res.token)
this.token = res.token
resolve()
}).catch(error => {
reject(error)
})
})
})
},
},
// 获取用户信息
getInfo() {
return new Promise((resolve, reject) => {
getInfo().then(res => {
const user = res.user
const avatar = (user.avatar == "" || user.avatar == null) ? defAva : import.meta.env.VITE_APP_BASE_API + user.avatar;
// 获取用户信息
GetInfo({ commit, state }) {
return new Promise((resolve, reject) => {
getInfo().then(res => {
const user = res.user
const avatar = (user.avatar == "" || user.avatar == null) ? defAva : import.meta.env.VITE_APP_BASE_API + user.avatar;
if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组
commit('SET_ROLES', res.roles)
commit('SET_PERMISSIONS', res.permissions)
} else {
commit('SET_ROLES', ['ROLE_DEFAULT'])
}
commit('SET_NAME', user.userName)
commit('SET_AVATAR', avatar)
resolve(res)
}).catch(error => {
reject(error)
if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组
this.roles = res.roles
this.permissions = res.permissions
} else {
this.setRoutes = ['ROLE_DEFAULT']
}
this.name = user.userName
this.avatar = avatar;
resolve(res)
}).catch(error => {
reject(error)
})
})
})
},
// 退出系统
LogOut({ commit, state }) {
return new Promise((resolve, reject) => {
logout(state.token).then(() => {
commit('SET_TOKEN', '')
commit('SET_ROLES', [])
commit('SET_PERMISSIONS', [])
removeToken()
resolve()
}).catch(error => {
reject(error)
},
// 退出系统
logOut() {
return new Promise((resolve, reject) => {
logout(this.token).then(() => {
this.token = ''
this.roles = []
this.permissions = []
removeToken()
resolve()
}).catch(error => {
reject(error)
})
})
})
},
// 前端 登出
FedLogOut({ commit }) {
return new Promise(resolve => {
commit('SET_TOKEN', '')
removeToken()
resolve()
})
}
}
}
}
})
export default user
export default useUserStore

@ -1,12 +1,14 @@
import store from '@/store'
import defaultSettings from '@/settings'
import useSettingsStore from '@/store/modules/settings'
/**
* 动态修改标题
*/
export function useDynamicTitle() {
if (store.state.settings.dynamicTitle) {
document.title = store.state.settings.title + ' - ' + defaultSettings.title;
const settingsStore = useSettingsStore();
if (settingsStore.dynamicTitle) {
document.title = settingsStore.title + ' - ' + defaultSettings.title;
} else {
document.title = defaultSettings.title;
}

@ -1,4 +1,4 @@
import store from '@/store'
import useUserStore from '@/store/modules/user'
/**
* 字符权限校验
@ -7,7 +7,7 @@ import store from '@/store'
*/
export function checkPermi(value) {
if (value && value instanceof Array && value.length > 0) {
const permissions = store.getters && store.getters.permissions
const permissions = useUserStore().permissions
const permissionDatas = value
const all_permission = "*:*:*";
@ -32,7 +32,7 @@ export function checkPermi(value) {
*/
export function checkRole(value) {
if (value && value instanceof Array && value.length > 0) {
const roles = store.getters && store.getters.roles
const roles = useUserStore().roles
const permissionRoles = value
const super_admin = "admin";

@ -1,11 +1,11 @@
import axios from 'axios'
import { ElNotification , ElMessageBox, ElMessage, ElLoading } from 'element-plus'
import store from '@/store'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { tansParams, blobValidate } from '@/utils/ruoyi'
import cache from '@/plugins/cache'
import { saveAs } from 'file-saver'
import useUserStore from '@/store/modules/user'
let downloadLoadingInstance;
// 是否显示重新登录
@ -85,7 +85,7 @@ service.interceptors.response.use(res => {
}
).then(() => {
isRelogin.show = false;
store.dispatch('LogOut').then(() => {
useUserStore().logOut().then(() => {
location.href = '/index';
})
}).catch(() => {

@ -68,8 +68,9 @@
import { getCodeImg } from "@/api/login";
import Cookies from "js-cookie";
import { encrypt, decrypt } from "@/utils/jsencrypt";
import useUserStore from '@/store/modules/user'
const store = useStore();
const userStore = useUserStore()
const router = useRouter();
const { proxy } = getCurrentInstance();
@ -111,7 +112,7 @@ function handleLogin() {
Cookies.remove("rememberMe");
}
// action
store.dispatch("Login", loginForm.value).then(() => {
userStore.login(loginForm.value).then(() => {
router.push({ path: redirect.value || "/" });
}).catch(() => {
loading.value = false;

@ -54,8 +54,9 @@
import "vue-cropper/dist/index.css";
import { VueCropper } from "vue-cropper";
import { uploadAvatar } from "@/api/system/user";
import useUserStore from '@/store/modules/user'
const store = useStore();
const userStore = useUserStore()
const { proxy } = getCurrentInstance();
const open = ref(false);
@ -64,7 +65,7 @@ const title = ref("修改头像");
//
const options = reactive({
img: store.getters.avatar, //
img: userStore.avatar, //
autoCrop: true, //
autoCropWidth: 200, //
autoCropHeight: 200, //
@ -116,7 +117,7 @@ function uploadImg() {
uploadAvatar(formData).then(response => {
open.value = false;
options.img = import.meta.env.VITE_APP_BASE_API + response.imgUrl;
store.commit("SET_AVATAR", options.img);
userStore.avatar = options.img;
proxy.$modal.msgSuccess("修改成功");
visible.value = false;
});
@ -128,7 +129,7 @@ function realTime(data) {
};
/** 关闭窗口 */
function closeDialog() {
options.img = store.getters.avatar;
options.img = userStore.avatar;
options.visible = false;
};
</script>

@ -5,9 +5,7 @@ export default function createAutoImport() {
imports: [
'vue',
'vue-router',
{
'vuex': ['useStore']
}
'pinia'
],
dts: false
})

Loading…
Cancel
Save