Browse Source

同步cli website加入大量配置

smallwei 6 years ago
parent
commit
581e293729

+ 13 - 1
src/const/website.js

@@ -16,6 +16,18 @@ export default {
             '当前版本:v2.0.0',
         ]
     },
+    //http的status默认放行不才用统一处理的,
+    statusWhiteList: [400],
+    //配置首页不可关闭
+    isFirstPage: false,
+    fistPage: {
+        label: "首页",
+        value: "/wel/index",
+        params: {},
+        query: {},
+        group: [],
+        close: false
+    },
     //配置菜单的属性
     menu: {
         props: {
@@ -25,4 +37,4 @@ export default {
             children: 'children'
         }
     }
-}
+}

+ 2 - 1
src/page/index/sidebar/index.vue

@@ -43,4 +43,5 @@ export default {
 }
 </script>
 <style lang="scss" scoped>
-</style>
+</style>
+

+ 8 - 2
src/page/index/sidebar/sidebarItem.vue

@@ -5,7 +5,7 @@
                     :index="item[pathKey]"
                     @click="open(item)"
                     :key="item[labelKey]"
-                    :class="{'is-active':nowTagValue===item[pathKey]}">
+                    :class="{'is-active':vaildAvtive(item)}">
         <i :class="item[iconKey]"></i>
         <span slot="title">{{item[labelKey]}}</span>
       </el-menu-item>
@@ -20,7 +20,7 @@
         <template v-for="(child,cindex) in item[childrenKey]">
           <el-menu-item :index="child[pathKey],cindex"
                         @click="open(child)"
-                        :class="{'is-active':nowTagValue===child[pathKey]}"
+                        :class="{'is-active':vaildAvtive(child)}"
                         v-if="validatenull(child[childrenKey])"
                         :key="child[labelKey]">
             <i :class="child[iconKey]"></i>
@@ -75,6 +75,10 @@ export default {
     nowTagValue () { return this.$router.$avueRouter.getValue(this.$route) }
   },
   methods: {
+    vaildAvtive (item) {
+      const groupFlag = (item['group'] || []).some(ele => this.$route.path.includes(ele));
+      return this.nowTagValue === item[this.pathKey] || groupFlag
+    },
     vaildRoles (item) {
       item.meta = item.meta || {};
       return item.meta.roles ? item.meta.roles.includes(this.roles) : true
@@ -84,6 +88,7 @@ export default {
     },
     open (item) {
       if (this.screen <= 1) this.$store.commit("SET_COLLAPSE");
+      this.$router.$avueRouter.group = item.group;
       this.$router.push({
         path: this.$router.$avueRouter.getPath({
           name: item[this.labelKey],
@@ -95,3 +100,4 @@ export default {
   }
 }
 </script>
+

+ 1 - 0
src/page/index/tags.vue

@@ -114,3 +114,4 @@ export default {
 }
 </script>
 
+

+ 23 - 5
src/permission.js

@@ -1,12 +1,29 @@
+/**
+ * 全站权限配置
+ * 
+ */
 import router from './router/router'
 import store from './store'
+import { validatenull } from '@/util/validate'
 import { getToken } from '@/util/auth'
 import NProgress from 'nprogress' // progress bar
 import 'nprogress/nprogress.css' // progress bar style
 NProgress.configure({ showSpinner: false });
 const lockPage = store.getters.website.lockPage; //锁屏页
 router.beforeEach((to, from, next) => {
-    NProgress.start()
+    //缓冲设置
+    if (to.meta.keepAlive === true && store.state.tags.tagList.some(ele => {
+            return ele.value === to.fullPath;
+        })) {
+        to.meta.$keepAlive = true;
+    } else {
+        NProgress.start()
+        if (to.meta.keepAlive === true && validatenull(to.meta.$keepAlive)) {
+            to.meta.$keepAlive = true;
+        } else {
+            to.meta.$keepAlive = false;
+        }
+    }
     const meta = to.meta || {};
     if (getToken()) {
         if (store.getters.isLock && to.path != lockPage) {
@@ -23,14 +40,15 @@ router.beforeEach((to, from, next) => {
                     })
                 })
             } else {
-                if (meta.isTab !== false) {
-                    const value = to.query.src ? to.query.src : to.fullPath;
-                    const label = to.query.name ? to.query.name : to.name;
+                const value = to.query.src || to.fullPath;
+                const label = to.query.name || to.name;
+                if (meta.isTab !== false && !validatenull(value) && !validatenull(label)) {
                     store.commit('ADD_TAG', {
                         label: label,
                         value: value,
                         params: to.params,
-                        query: to.query
+                        query: to.query,
+                        group: router.$avueRouter.group || []
                     });
                 }
                 next()

+ 27 - 9
src/router/avue-router.js

@@ -1,6 +1,7 @@
 let RouterPlugin = function() {
     this.$router = null;
     this.$store = null;
+
 };
 RouterPlugin.install = function(router, store) {
     this.$router = router;
@@ -16,10 +17,12 @@ RouterPlugin.install = function(router, store) {
     this.$router.$avueRouter = {
         //全局配置
         $website: this.$store.getters.website,
+        routerList: [],
+        group: '',
         safe: this,
         // 设置标题
         setTitle: function(title) {
-            title = title ? `${title}——PigX Pro 快速开发框架` : 'PigX Pro 快速开发框架';
+            title = title ? `${title}——Avue 通用管理 系统快速开发框架` : 'Avue 通用管理 系统快速开发框架';
             document.title = title;
         },
         closeTag: (value) => {
@@ -57,22 +60,32 @@ RouterPlugin.install = function(router, store) {
             return value;
         },
         //动态路由
-        formatRoutes: function(aMenu, first) {
+        formatRoutes: function(aMenu = [], first) {
             const aRouter = []
             const propsConfig = this.$website.menu.props;
             const propsDefault = {
                 label: propsConfig.label || 'label',
                 path: propsConfig.path || 'path',
                 icon: propsConfig.icon || 'icon',
-                children: propsConfig.children || 'children'
+                children: propsConfig.children || 'children',
+                meta: propsConfig.meta || 'meta',
             }
-            if (!aMenu) return;
-            aMenu.forEach(oMenu => {
-                const path = oMenu[propsDefault.path],
+            if (aMenu.length === 0) return;
+            for (let i = 0; i < aMenu.length; i++) {
+                const oMenu = aMenu[i];
+                if (this.routerList.includes(oMenu[propsDefault.path])) return;
+                const path = (() => {
+                        if (first) {
+                            return oMenu[propsDefault.path].replace('/index', '')
+                        } else {
+                            return oMenu[propsDefault.path]
+                        }
+                    })(),
                     component = oMenu.component,
                     name = oMenu[propsDefault.label],
                     icon = oMenu[propsDefault.icon],
-                    children = oMenu[propsDefault.children];
+                    children = oMenu[propsDefault.children],
+                    meta = oMenu[propsDefault.meta];
 
                 const isChild = children.length !== 0;
                 const oRouter = {
@@ -93,6 +106,7 @@ RouterPlugin.install = function(router, store) {
                     },
                     name: name,
                     icon: icon,
+                    meta: meta,
                     redirect: (() => {
                         if (!isChild && first) return `${path}/index`
                         else return '';
@@ -105,6 +119,7 @@ RouterPlugin.install = function(router, store) {
                                 component(resolve) { require([`../${component}.vue`], resolve) },
                                 icon: icon,
                                 name: name,
+                                meta: meta,
                                 path: 'index'
                             }]
                         }
@@ -114,9 +129,12 @@ RouterPlugin.install = function(router, store) {
                     })()
                 }
                 aRouter.push(oRouter)
-            })
+            }
             if (first) {
-                this.safe.$router.addRoutes(aRouter)
+                if (!this.routerList.includes(aRouter[0][propsDefault.path])) {
+                    this.safe.$router.addRoutes(aRouter)
+                    this.routerList.push(aRouter[0][propsDefault.path])
+                }
             } else {
                 return aRouter
             }

+ 12 - 8
src/router/axios.js

@@ -1,11 +1,13 @@
 /**
+ * 全站http配置
  *
- * http配置
- *
+ * header参数说明
+ * serialize是否开启form表单提交
+ * isToken是否需要token
  */
-// 引入axios以及element ui中的loading和message组件
 import axios from 'axios'
 import { serialize } from '@/util/util'
+import website from '@/const/website'
 import store from '../store'
 import { getStore } from '../util/store'
 import { getToken } from '@/util/auth'
@@ -27,7 +29,8 @@ NProgress.configure({
 //HTTPrequest拦截
 axios.interceptors.request.use(config => {
     NProgress.start() // start progress bar
-    if (store.getters.access_token) {
+    const isToken = (config.data || {}).isToken === false
+    if (store.getters.access_token && !isToken) {
         config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带token--['X-Token']为自定义key 请根据实际情况自行修改
     }
     const TENANT_ID = getStore({ name: 'tenantId' });
@@ -46,17 +49,18 @@ axios.interceptors.request.use(config => {
 //HTTPresponse拦截
 axios.interceptors.response.use(res => {
     NProgress.done();
-    const status = Number(res.status);
+    const status = Number(res.status) || 200;
+    const statusWhiteList = website.statusWhiteList || [];
     const message = res.data.data || errorCode[status] || errorCode['default'];
 
-    if (status === 401){
+    if (status === 401) {
         store.dispatch('FedLogOut').then(() => {
             router.push({
                 path: '/login'
             });
         })
     }
-    if (status !== 200) {
+    if (status !== 200 & !statusWhiteList.includes(status)) {
         Message({
             message: message,
             type: 'error'
@@ -69,4 +73,4 @@ axios.interceptors.response.use(res => {
     return Promise.reject(new Error(error))
 })
 
-export default axios
+export default axios

+ 17 - 16
src/store/modules/tags.js

@@ -1,19 +1,26 @@
 import { setStore, getStore } from '@/util/store'
 import { diff } from '@/util/util'
+import website from '@/const/website'
+const isFirstPage = website.isFirstPage;
+const tagWel = website.fistPage;
 const tagObj = {
-    label: '', //标题名称
-    value: '', //标题的路径
-    params: '', //标题的路径参数
-    query: '', //标题的参数
-}
-
-//处理首个标签
+        label: '', //标题名称
+        value: '', //标题的路径
+        params: '', //标题的路径参数
+        query: '', //标题的参数
+        group: [], //分组
+    }
+    //处理首个标签
 function setFistTag(list) {
     if (list.length == 1) {
         list[0].close = false;
     } else {
-        list.some(a => {
-            a.close = true
+        list.forEach(ele => {
+            if (ele.value === tagWel.value && isFirstPage === false) {
+                ele.close = false
+            } else {
+                ele.close = true
+            }
         })
     }
 }
@@ -23,13 +30,7 @@ const navs = {
     state: {
         tagList: getStore({ name: 'tagList' }) || [],
         tag: getStore({ name: 'tag' }) || tagObj,
-        tagWel: {
-            label: "首页",
-            value: "/wel/index",
-            params: {},
-            query: {},
-            close: false
-        }
+        tagWel: tagWel
     },
     actions: {
 

+ 14 - 9
src/store/modules/user.js

@@ -1,11 +1,12 @@
 import { setToken, removeToken } from '@/util/auth'
 import { setStore, getStore } from '@/util/store'
-import { logout, loginByUsername,loginByMobile, loginBySocial, getUserInfo } from '@/api/login'
-import { encryption } from '@/util/util'
+import { isURL } from '@/util/validate'
+import { logout, loginByUsername, loginByMobile, loginBySocial, getUserInfo } from '@/api/login'
+import { encryption, deepClone } from '@/util/util'
 import webiste from '@/const/website';
 import { GetMenu } from '@/api/menu'
 
-function addPath(ele) {
+function addPath(ele, first) {
     const propsConfig = webiste.menu.props;
     const propsDefault = {
         label: propsConfig.label || 'label',
@@ -14,9 +15,12 @@ function addPath(ele) {
         children: propsConfig.children || 'children'
     }
     const isChild = ele[propsDefault.children] && ele[propsDefault.children].length !== 0;
-    if (!isChild) return
+    if (!isChild && first) {
+        ele[propsDefault.path] = ele[propsDefault.path] + '/index'
+        return
+    }
     ele[propsDefault.children].forEach(child => {
-        if (!child[propsDefault.path].includes('http') && !child[propsDefault.path].includes('https')) {
+        if (!isURL(child[propsDefault.path])) {
             child[propsDefault.path] = `${ele[propsDefault.path]}/${child[propsDefault.path]?child[propsDefault.path]:'index'}`
         }
         addPath(child);
@@ -153,11 +157,12 @@ const user = {
             return new Promise(resolve => {
                 GetMenu().then((res) => {
                     const data = res.data.data
-                    data.forEach(ele => {
+                    let menu = deepClone(data);
+                    menu.forEach(ele => {
                         addPath(ele);
                     })
-                    commit('SET_MENU', data)
-                    resolve(data)
+                    commit('SET_MENU', menu)
+                    resolve(menu)
                 })
             })
         }
@@ -208,4 +213,4 @@ const user = {
     }
 
 }
-export default user
+export default user

+ 44 - 0
src/util/util.js

@@ -7,6 +7,50 @@ export const serialize = data => {
     })
     return list.join('&');
 };
+export const getObjType = obj => {
+    var toString = Object.prototype.toString;
+    var map = {
+        '[object Boolean]': 'boolean',
+        '[object Number]': 'number',
+        '[object String]': 'string',
+        '[object Function]': 'function',
+        '[object Array]': 'array',
+        '[object Date]': 'date',
+        '[object RegExp]': 'regExp',
+        '[object Undefined]': 'undefined',
+        '[object Null]': 'null',
+        '[object Object]': 'object'
+    };
+    if (obj instanceof Element) {
+        return 'element';
+    }
+    return map[toString.call(obj)];
+};
+/**
+ * 对象深拷贝
+ */
+export const deepClone = data => {
+    var type = getObjType(data);
+    var obj;
+    if (type === 'array') {
+        obj = [];
+    } else if (type === 'object') {
+        obj = {};
+    } else {
+        //不再具有下一层次
+        return data;
+    }
+    if (type === 'array') {
+        for (var i = 0, len = data.length; i < len; i++) {
+            obj.push(deepClone(data[i]));
+        }
+    } else if (type === 'object') {
+        for (var key in data) {
+            obj[key] = deepClone(data[key]);
+        }
+    }
+    return obj;
+};
 /**
  * 判断路由是否相等
  */

+ 28 - 1
src/util/validate.js

@@ -1,7 +1,34 @@
 /**
- * Created by jiachenpan on 16/11/18.
+ * 邮箱
+ * @param {*} s
  */
+export function isEmail(s) {
+    return /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/.test(s)
+}
+
+/**
+ * 手机号码
+ * @param {*} s
+ */
+export function isMobile(s) {
+    return /^1[0-9]{10}$/.test(s)
+}
+
+/**
+ * 电话号码
+ * @param {*} s
+ */
+export function isPhone(s) {
+    return /^([0-9]{3,4}-)?[0-9]{7,8}$/.test(s)
+}
 
+/**
+ * URL地址
+ * @param {*} s
+ */
+export function isURL(s) {
+    return /^http[s]?:\/\/.*/.test(s)
+}
 export function isvalidUsername(str) {
     const valid_map = ['admin', 'editor']
     return valid_map.indexOf(str.trim()) >= 0