diff --git a/mock/login.js b/mock/login.js index 20d1d75..3405e40 100644 --- a/mock/login.js +++ b/mock/login.js @@ -23,7 +23,7 @@ export default [ data: { id: 1, name: 'zhangsan', - role: 'visitor', + 'role|1': ['admin', 'visitor'], // 随机返回一个角色admin或visitor avatar: "@image('48x48', '#fb0a2a')" } }, diff --git a/src/assets/style/global-variables.scss b/src/assets/style/global-variables.scss index 7a16833..7c88bb1 100644 --- a/src/assets/style/global-variables.scss +++ b/src/assets/style/global-variables.scss @@ -2,7 +2,7 @@ $mainColor: #409eff; // 网站主题色 -// 菜单配置 +// 侧边栏 $menuBg: #304156; // 菜单背景颜色 $menuTextColor: #fff; // 菜单文字颜色 $menuActiveTextColor: $mainColor; // 已选中菜单文字颜色 diff --git a/src/layout/components/Content/index.vue b/src/layout/components/Content/index.vue index 562b2b4..82b296a 100644 --- a/src/layout/components/Content/index.vue +++ b/src/layout/components/Content/index.vue @@ -1,16 +1,9 @@ - - \ No newline at end of file diff --git a/src/layout/components/Sidebar/Menus.vue b/src/layout/components/Sidebar/Menus.vue index 10cf648..3d80d78 100644 --- a/src/layout/components/Sidebar/Menus.vue +++ b/src/layout/components/Sidebar/Menus.vue @@ -10,13 +10,7 @@ :text-color="variables.menuTextColor" :active-text-color="variables.menuActiveTextColor" > - - - + diff --git a/src/layout/components/Sidebar/index.vue b/src/layout/components/Sidebar/index.vue index 15d9858..f622f13 100644 --- a/src/layout/components/Sidebar/index.vue +++ b/src/layout/components/Sidebar/index.vue @@ -1,11 +1,12 @@ + border-bottom: 1px solid #eaeaea; - diff --git a/src/layout/components/Topbar/Breadcrumbs.vue b/src/layout/components/Topbar/Breadcrumbs.vue index 4203a7c..7a347ec 100644 --- a/src/layout/components/Topbar/Breadcrumbs.vue +++ b/src/layout/components/Topbar/Breadcrumbs.vue @@ -2,23 +2,27 @@ - {{item.meta.title}} + {{ item.meta.title }} \ No newline at end of file diff --git a/src/layout/hooks/useResizeHandler.js b/src/layout/hooks/useResizeHandler.js new file mode 100644 index 0000000..c797db6 --- /dev/null +++ b/src/layout/hooks/useResizeHandler.js @@ -0,0 +1,46 @@ +import { onBeforeMount, onBeforeUnmount, watch } from "vue" +import { useRouter } from "vue-router" +import { useStore } from "vuex" + +const WIDTH = 768 +export const useResizeHandler = () => { + const store = useStore() + const router = useRouter() + const route = router.currentRoute + + const isMobile = () => { + return window.innerWidth < WIDTH + } + + const resizeHandler = () => { + if (isMobile()) { + store.commit('app/setDevice', 'mobile') + store.commit('app/setCollapse', 1) + } else { + store.commit('app/setDevice', 'desktop') + store.commit('app/setCollapse', 0) + } + } + + onBeforeMount(() => { + if (isMobile()) { + store.commit('app/setDevice', 'mobile') + store.commit('app/setCollapse', 1) + } + window.addEventListener('resize', resizeHandler) + }) + + onBeforeUnmount(() => { + window.removeEventListener('resize', resizeHandler) + }) + + // // 监听路由的时候不能使用useRoute获取路由,否则会有警告 + // watch(route, () => { + // if (store.state.app.device === 'mobile' && !store.state.app.sidebar.collapse) { + // store.commit('app/setCollapse', 1) + // } + // }) + +} + + diff --git a/src/layout/index.vue b/src/layout/index.vue index 0389394..fa99834 100644 --- a/src/layout/index.vue +++ b/src/layout/index.vue @@ -6,7 +6,9 @@ - +
+ +
@@ -16,14 +18,19 @@ import Sidebar from "./components/Sidebar/index.vue"; import Topbar from "./components/Topbar/index.vue"; import Tagsbar from "./components/Tagsbar/index.vue"; import Content from "./components/Content/index.vue"; +import { useResizeHandler } from "./hooks/useResizeHandler"; export default defineComponent({ + name: "layout", components: { Sidebar, Topbar, Tagsbar, Content, }, + setup() { + useResizeHandler(); + }, }); @@ -34,11 +41,18 @@ export default defineComponent({ .right { flex: 1; + overflow: hidden; display: flex; flex-direction: column; .top { background: #fff; } + .main { + flex: 1; + background: #f0f2f5; + padding: 16px; + overflow: auto; + } } } \ No newline at end of file diff --git a/src/router/index.js b/src/router/index.js index bd376f3..14c29e9 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -1,6 +1,7 @@ // index.js import { createRouter, createWebHashHistory } from "vue-router" +import redirect from './modules/redirect' import error from './modules/error' import login from './modules/login' import home from './modules/home' @@ -20,10 +21,18 @@ const router = createRouter({ path: '/', redirect: '/home', }, + ...redirect, // 统一的重定向配置 ...login, ...allMenus, ...error ], + scrollBehavior (to, from, savedPosition) { + if (savedPosition) { + return savedPosition + } else { + return { left: 0, top: 0 } + } + }, }); export default router; \ No newline at end of file diff --git a/src/router/modules/error.js b/src/router/modules/error.js index 70f11fb..0238cd6 100644 --- a/src/router/modules/error.js +++ b/src/router/modules/error.js @@ -1,16 +1,17 @@ -import layout from '@/layout/index.vue' +const Layout = () => import('@/layout/index.vue') const Error = () => import("@/views/error/index.vue"); export default [ { path: '/error', - component: layout, + component: Layout, children: [ { path: '403', name: 'error-forbidden', component: Error, + meta: { title: '403' }, props: { error: '403' } @@ -19,6 +20,7 @@ export default [ path: '500', name: 'error-server-error', component: Error, + meta: { title: '500' }, props: { error: '500' } @@ -27,6 +29,7 @@ export default [ path: '404', name: 'error-not-found', component: Error, + meta: { title: '404' }, props: { error: '404' } diff --git a/src/router/modules/home.js b/src/router/modules/home.js index 4271c55..866773e 100644 --- a/src/router/modules/home.js +++ b/src/router/modules/home.js @@ -1,11 +1,11 @@ // home.js -import layout from '@/layout/index.vue' +const Layout = () => import('@/layout/index.vue') const Home = () => import("@/views/home/index.vue"); export default [ { path: '/home', - component: layout, + component: Layout, name: "Dashboard", meta: { title: "Dashboard", @@ -18,6 +18,7 @@ export default [ component: Home, meta: { title: "首页", + affix: true } } ] diff --git a/src/router/modules/redirect.js b/src/router/modules/redirect.js new file mode 100644 index 0000000..08d5792 --- /dev/null +++ b/src/router/modules/redirect.js @@ -0,0 +1,8 @@ +const Redirect = () => import("@/views/redirect/index.vue"); + +export default [ + { + path: '/redirect/:path(.*)', + component: Redirect, + } +] \ No newline at end of file diff --git a/src/router/modules/test.js b/src/router/modules/test.js index 1e3d35c..b1bae09 100644 --- a/src/router/modules/test.js +++ b/src/router/modules/test.js @@ -1,15 +1,18 @@ -import layout from '@/layout/index.vue' +const Layout = () => import('@/layout/index.vue') const List = () => import("@/views/test/index.vue"); const Add = () => import("@/views/test/Add.vue"); const Auth = () => import("@/views/test/Auth.vue"); +const NoAuth = () => import("@/views/test/NoAuth.vue"); const Nest = () => import("@/views/test/Nest.vue"); const NestPage1 = () => import("@/views/test/nest/Page1.vue"); const NestPage2 = () => import("@/views/test/nest/Page2.vue"); +const Iscache = () => import("@/views/test/Cache.vue"); +const Nocache = () => import("@/views/test/Nocache.vue"); export default [ { path: '/test', - component: layout, + component: Layout, name: "test", meta: { title: "测试页面", @@ -40,9 +43,38 @@ export default [ path: "auth", name: "testAuth", component: Auth, + meta: { + title: "权限测试", + roles: ["admin", "visitor"], + } + }, + { + path: "noauth", + name: "testNoAuth", + component: NoAuth, meta: { title: "权限页面", roles: ["admin"], + }, + hidden: true + }, + { + path: "cache", + name: "test-cache", + component: Iscache, + meta: { + title: "该页面可缓存", + roles: ["admin", "visitor"] + } + }, + { + path: "nocache", + name: "test-no-cache", + component: Nocache, + meta: { + title: "该页面不缓存", + roles: ["admin", "visitor"], + noCache: true, // 不缓存页面 } }, { diff --git a/src/store/modules/app.js b/src/store/modules/app.js index 8dea054..58e791b 100644 --- a/src/store/modules/app.js +++ b/src/store/modules/app.js @@ -1,5 +1,6 @@ import { getItem, setItem, removeItem } from "@/utils/storage"; //getItem和setItem是封装的操作localStorage的方法 -export const TOKEN = "TOKEN"; +export const TOKEN = "VEA-TOKEN"; +const COLLAPSE = "VEA-COLLAPSE"; export default { namespaced: true, @@ -7,8 +8,9 @@ export default { title: 'Vue3 Element Admin', authorization: getItem(TOKEN), sidebar: { - collapse: getItem('collapse') - } + collapse: getItem(COLLAPSE) + }, + device: 'desktop', }, mutations: { setToken (state, data) { @@ -18,19 +20,22 @@ export default { }, clearToken (state) { state.authorization = ''; - // 保存到localStorage + removeItem(TOKEN); }, setCollapse (state, data) { state.sidebar.collapse = data; // 保存到localStorage - setItem('collapse', data); + setItem(COLLAPSE, data); }, clearCollapse (state) { state.sidebar.collapse = ''; - // 保存到localStorage - removeItem('collapse'); - } + + removeItem(COLLAPSE); + }, + setDevice (state, device) { + state.device = device + }, }, actions: {}, }; \ No newline at end of file diff --git a/src/store/modules/tags.js b/src/store/modules/tags.js index 413e6c1..6d26b2a 100644 --- a/src/store/modules/tags.js +++ b/src/store/modules/tags.js @@ -1,20 +1,28 @@ +import { getItem, setItem, removeItem } from "@/utils/storage"; //getItem和setItem是封装的操作localStorage的方法 + +const TAGLIST = 'VEA-TAGLIST' + const state = { - tagList: [], + tagList: getItem(TAGLIST) || [], cacheList: [], activePosition: 0 } const mutations = { - ADD_TAG_LIST: (state, tag) => { - if (state.tagList.some(v => v.path === tag.path)) return; + ADD_TAG_LIST: (state, { path, fullPath, name, meta }) => { + if (state.tagList.some(v => v.path === path)) return false; + state.tagList.splice( state.activePosition + 1, 0, - Object.assign({}, tag, { - title: tag.meta.title || 'no-name' + Object.assign({}, { path, fullPath, name, meta }, { + title: meta.title || '未命名', + fullPath: fullPath || path }) ) + // 保存到localStorage + setItem(TAGLIST, state.tagList); }, ADD_CACHE_LIST: (state, tag) => { if (state.cacheList.includes(tag.name)) return @@ -25,6 +33,8 @@ const mutations = { DEL_TAG_LIST: (state, tag) => { state.tagList = state.tagList.filter(v => v.path !== tag.path) + // 保存到localStorage + setItem(TAGLIST, state.tagList); }, DEL_CACHE_LIST: (state, tag) => { state.cacheList = state.cacheList.filter(v => v !== tag.name) @@ -32,6 +42,8 @@ const mutations = { DEL_OTHER_TAG_LIST: (state, tag) => { state.tagList = state.tagList.filter(v => !!v.meta.affix || v.path === tag.path) + // 保存到localStorage + setItem(TAGLIST, state.tagList); }, DEL_OTHER_CACHE_LIST: (state, tag) => { state.cacheList = state.cacheList.filter(v => v === tag.name) @@ -39,6 +51,8 @@ const mutations = { DEL_ALL_TAG_LIST: state => { state.tagList = state.tagList.filter(v => !!v.meta.affix) + // 保存到localStorage + removeItem(TAGLIST); }, DEL_ALL_CACHE_LIST: state => { state.cacheList = [] @@ -47,7 +61,9 @@ const mutations = { UPDATE_TAG_LIST: (state, tag) => { const index = state.tagList.findIndex(v => v.path === tag.path); if (index > -1) { - state.tagList[index] = Object.assign({}, tag) + state.tagList[index] = Object.assign({}, state.tagList[index], tag) + // 保存到localStorage + setItem(TAGLIST, state.tagList); } }, diff --git a/src/views/home/index.vue b/src/views/home/index.vue index cf5f445..c5c71ac 100644 --- a/src/views/home/index.vue +++ b/src/views/home/index.vue @@ -1,6 +1,16 @@ + + +