diff --git a/vue/src/layout/components/Footer.vue b/vue/src/layout/components/Footer.vue index 2aff0bc..da2e3e7 100644 --- a/vue/src/layout/components/Footer.vue +++ b/vue/src/layout/components/Footer.vue @@ -1,6 +1,8 @@ @@ -14,5 +16,10 @@ .page-footer { padding: 48px 24px 24px 24px; text-align: center; + + .copyright { + color: #808695; + font-size: 14px; + } } diff --git a/vue/src/layout/components/Main.vue b/vue/src/layout/components/Main.vue index 6014752..68b1096 100644 --- a/vue/src/layout/components/Main.vue +++ b/vue/src/layout/components/Main.vue @@ -29,8 +29,6 @@ import {mapState} from 'vuex' import Footer from "./Footer" - const FooterConstructor = Vue.extend(Footer) - export default { name: 'AppMain', computed: { @@ -52,13 +50,13 @@ }, watch: { scrollTop(v) { - if (v >= 0) this.$refs.scrollbar.$refs['wrap'].scrollTop = v + if (v >= 0) this.$refs.scrollbar.$refs.wrap.scrollTop = v } }, mounted() { //插入footer - const footerInstance = new FooterConstructor() - footerInstance.$mount() + const FooterConstructor = Vue.extend(Footer) + const footerInstance = new FooterConstructor().$mount() this.$refs.scrollbar.$refs.wrap.appendChild(footerInstance.$el) } } diff --git a/vue/src/router/authority/index.js b/vue/src/router/authority/index.js new file mode 100644 index 0000000..f5e3121 --- /dev/null +++ b/vue/src/router/authority/index.js @@ -0,0 +1,9 @@ +/*需要权限控制的路由表*/ +const modulesFiles = require.context('./modules', false, /\.js$/) +const modules = modulesFiles.keys().reduce((modules, modulePath) => { + const value = modulesFiles(modulePath).default + Array.isArray(value) ? modules.push(...value) : modules.push(value) + return modules +}, []) + +export default modules diff --git a/vue/src/router/modules/message.js b/vue/src/router/authority/modules/message.js similarity index 100% rename from vue/src/router/modules/message.js rename to vue/src/router/authority/modules/message.js diff --git a/vue/src/router/modules/purchase.js b/vue/src/router/authority/modules/purchase.js similarity index 100% rename from vue/src/router/modules/purchase.js rename to vue/src/router/authority/modules/purchase.js diff --git a/vue/src/router/modules/sell.js b/vue/src/router/authority/modules/sell.js similarity index 100% rename from vue/src/router/modules/sell.js rename to vue/src/router/authority/modules/sell.js diff --git a/vue/src/router/modules/stock.js b/vue/src/router/authority/modules/stock.js similarity index 100% rename from vue/src/router/modules/stock.js rename to vue/src/router/authority/modules/stock.js diff --git a/vue/src/router/modules/system.js b/vue/src/router/authority/modules/system.js similarity index 100% rename from vue/src/router/modules/system.js rename to vue/src/router/authority/modules/system.js diff --git a/vue/src/router/authorityRoutes/index.js b/vue/src/router/authorityRoutes/index.js deleted file mode 100644 index c85548a..0000000 --- a/vue/src/router/authorityRoutes/index.js +++ /dev/null @@ -1,17 +0,0 @@ -/*需要权限控制的路由表*/ -import purchaseRouter from '@/router/modules/purchase' -import sellRouter from '@/router/modules/sell' -import stockRouter from '@/router/modules/stock' -import messageRouter from '@/router/modules/message' -import systemRouter from '@/router/modules/system' - - -const authorityRoutes = [ - purchaseRouter, - sellRouter, - stockRouter, - messageRouter, - systemRouter, -] - -export default authorityRoutes diff --git a/vue/src/router/constantRoutes/index.js b/vue/src/router/constant/index.js similarity index 54% rename from vue/src/router/constantRoutes/index.js rename to vue/src/router/constant/index.js index c9d3809..fab42aa 100644 --- a/vue/src/router/constantRoutes/index.js +++ b/vue/src/router/constant/index.js @@ -1,40 +1,23 @@ -/* -* 不需要权限控制的路由表 -* */ +/** + * 不需要权限控制的路由表 + * constant/modules下的所有route都会加上noAuth:true + */ import Layout from '@/layout' -import exampleRouter from '@/router/modules/example' -const constantRoutes = [ - { - path: '/redirect', - component: Layout, - children: [ - { - path: '/redirect/:path(.*)', - component: () => import('@/views/app/redirect') - } - ] - }, - { - path: '/login', - component: () => import('@/views/app/login') - }, - { - path: '/register', - component: () => import('@/views/app/register') - }, - { - path: '/404', - component: () => import('@/views/app/404') - }, - { - path: '/403', - component: () => import('@/views/app/403') - }, +const modulesFiles = require.context('./modules', false, /\.js$/) +const modules = modulesFiles.keys().reduce((modules, modulePath) => { + const value = modulesFiles(modulePath).default + Array.isArray(value) ? modules.push(...value) : modules.push(value) + return modules +}, []) + +const routes = [ + ...modules, { path: '/', component: Layout, redirect: '/index', + sort: 0, children: [ { path: 'index', @@ -57,8 +40,7 @@ const constantRoutes = [ } ], hidden: true - }, - exampleRouter + } ] function addNoAuth(routes) { @@ -69,6 +51,6 @@ function addNoAuth(routes) { }) } -addNoAuth(constantRoutes) +addNoAuth(routes) -export default constantRoutes +export default routes diff --git a/vue/src/router/constant/modules/app.js b/vue/src/router/constant/modules/app.js new file mode 100644 index 0000000..af1626b --- /dev/null +++ b/vue/src/router/constant/modules/app.js @@ -0,0 +1,33 @@ +/*路由表:系统页面*/ +import Layout from '@/layout' + +const router = [ + { + path: '/redirect', + component: Layout, + children: [ + { + path: '/redirect/:path(.*)', + component: () => import('@/views/app/redirect') + } + ] + }, + { + path: '/login', + component: () => import('@/views/app/login') + }, + { + path: '/register', + component: () => import('@/views/app/register') + }, + { + path: '/404', + component: () => import('@/views/app/404') + }, + { + path: '/403', + component: () => import('@/views/app/403') + } +] + +export default router diff --git a/vue/src/router/modules/example.js b/vue/src/router/constant/modules/example.js similarity index 100% rename from vue/src/router/modules/example.js rename to vue/src/router/constant/modules/example.js diff --git a/vue/src/router/index.js b/vue/src/router/index.js index d39677d..aa727b8 100644 --- a/vue/src/router/index.js +++ b/vue/src/router/index.js @@ -3,6 +3,7 @@ * * 需要鉴权的路由:meta && !meta.noAuth * 左侧菜单显示:name && !hidden && meta.title +* 左侧菜单排序:能显示 && sort,升序排列 * 左侧菜单不折叠只有一个children的路由:alwaysShow * 面包屑显示:meta.title * 搜索选项显示:name && meta.title @@ -12,14 +13,13 @@ * */ import Vue from 'vue' import Router from 'vue-router' -import {pathToRegexp} from 'path-to-regexp' import NProgress from 'nprogress' import {isUserExist} from "@/utils/sessionStorage" import {auth, needAuth} from "@/utils/auth" -import {isEmpty} from "@/utils" -import {title, routerMode} from '@/config' -import constantRoutes from '@/router/constantRoutes' -import authorityRoutes from '@/router/authorityRoutes' +import {getPageTitle, transformWhiteList, metaExtend} from './util' +import {routerMode} from '@/config' +import constantRoutes from '@/router/constant' +import authorityRoutes from '@/router/authority' import store from "@/store" Vue.use(Router) @@ -28,9 +28,7 @@ NProgress.configure({showSpinner: false}) const endRoute = [{path: '*', redirect: '/404', hidden: true}] -const urlNoNeedLogin = [ - '/login', '/register', '/404', '/403' -].map(url => pathToRegexp(url)) +const whiteList = transformWhiteList(['/login', '/register', '/404', '/403']) metaExtend(constantRoutes) metaExtend(authorityRoutes) @@ -47,8 +45,8 @@ router.beforeEach(async (to, from, next) => { document.title = getPageTitle(to.meta.title) - //不需要登录的页面也不需要进行权限控制 - if (urlNoNeedLogin.some(reg => reg.test(to.path))) return next() + //白名单内不需要进行权限控制 + if (whiteList.some(reg => reg.test(to.path))) return next() const isLogin = isUserExist() @@ -81,32 +79,10 @@ function initMenu() { return Promise.resolve() } -//拼接页面标题 -function getPageTitle(pageTitle) { - return pageTitle ? `${pageTitle} - ${title}` : title -} - //判断是否需要打开iframe function iframeControl(route) { let operate = route.meta.iframe ? 'open' : 'close' store.dispatch(`iframe/${operate}`, route.meta.iframe) } -//子路由继承父路由meta上的{affix,noAuth,noCache},优先使用子路由的值 -function metaExtend(routes, meta) { - routes.forEach(route => { - if (meta) { - const keys = ['affix', 'noAuth', 'noCache'] - Object.keys(meta).forEach(key => { - if (keys.includes(key) && !isEmpty(meta[key]) && isEmpty(route.meta[key])) { - route.meta[key] = meta[key] - } - }) - } - if (route.children) { - metaExtend(route.children, route.meta) - } - }) -} - export default router diff --git a/vue/src/router/util.js b/vue/src/router/util.js new file mode 100644 index 0000000..34effee --- /dev/null +++ b/vue/src/router/util.js @@ -0,0 +1,30 @@ +import {pathToRegexp} from 'path-to-regexp' +import {isEmpty} from "@/utils" +import {title} from "@/config" + +//拼接页面标题 +export function getPageTitle(pageTitle) { + return pageTitle ? `${pageTitle} - ${title}` : title +} + +//将给定的白名单url转换为正则 +export function transformWhiteList(list) { + return list.map(url => pathToRegexp(url)) +} + +//子路由继承父路由meta上的{affix,noAuth,noCache},优先使用子路由的值 +export function metaExtend(routes, meta) { + routes.forEach(route => { + if (meta) { + const keys = ['affix', 'noAuth', 'noCache'] + Object.keys(meta).forEach(key => { + if (keys.includes(key) && !isEmpty(meta[key]) && isEmpty(route.meta[key])) { + route.meta[key] = meta[key] + } + }) + } + if (route.children) { + metaExtend(route.children, route.meta) + } + }) +} diff --git a/vue/src/store/modules/resource.js b/vue/src/store/modules/resource.js index f65f709..11ceb3b 100644 --- a/vue/src/store/modules/resource.js +++ b/vue/src/store/modules/resource.js @@ -1,10 +1,11 @@ import path from 'path' -import constantRoutes from '@/router/constantRoutes' -import authorityRoutes from '@/router/authorityRoutes' +import constantRoutes from '@/router/constant' +import authorityRoutes from '@/router/authority' import {needAuth} from "@/utils/auth" import {createTree} from "@/utils/tree" import {getLocalResource, setLocalResource} from "@/utils/localStorage" import {getResources} from "@/api/system/resource" +import {isEmpty} from "@/utils" const finalConstantRoutes = transformOriginRoutes(constantRoutes) const finalAuthorityRoutes = transformOriginRoutes(authorityRoutes) @@ -26,10 +27,15 @@ const mutations = { routes(state, routes) { let tempConstantRoutes = JSON.parse(JSON.stringify(finalConstantRoutes)) let tempAuthorityRoutes = JSON.parse(JSON.stringify(routes)) + clean(tempConstantRoutes) clean(tempAuthorityRoutes) + state.routes = finalConstantRoutes.concat(routes) - state.sidebarMenus = tempConstantRoutes.concat(tempAuthorityRoutes) + + const sidebarMenus = tempConstantRoutes.concat(tempAuthorityRoutes) + sort(sidebarMenus) + state.sidebarMenus = sidebarMenus }, data(state, data) { state.data = data || [] @@ -140,6 +146,39 @@ function filter(arr, fun) { } } +//菜单排序 +function sort(routes, getSortValue = defaultGetSortValue) { + routes.sort((pre, next) => { + const preSort = getSortValue(pre), + nextSort = getSortValue(next) + if (preSort < nextSort) return -1 + else if (preSort === nextSort) return 0 + else return 1 + }) + routes.forEach(route => { + if (route.children && route.children.length > 1) { + sort(route.children, getSortValue) + } + }) +} + +const defaultGetSortValue = item => { + item = deepTap(item) + return !item || isEmpty(item.sort) ? 10000 : item.sort +} + +const deepTap = item => { + if (item.hidden) return null + if (!isEmpty(item.sort)) return item + if (isEmpty(item.name, item.meta.title)) { + //如果是类似首页那样的路由层级 + if (item.children && item.children.length === 1) { + return deepTap(item.children[0]) + } + } + return null +} + export default { namespaced: true, state,