From c1b532ad9ca4f9d04954c7dd1d1b601b43ff0440 Mon Sep 17 00:00:00 2001 From: 梁保满 Date: Tue, 29 Nov 2022 16:22:49 +0800 Subject: [PATCH] 权限配置,路由基础设置 --- src/api/apis/login.js | 10 ++++++++++ src/api/apis/role.js | 23 +++++++++++++++++++++++ src/api/apis/user.js | 35 +++++++++++++++++++++++++++++++++++ src/api/axios.js | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/api/index.js | 8 ++++++++ src/api/urls/login.js | 5 +++++ src/api/urls/role.js | 12 ++++++++++++ src/api/urls/user.js | 17 +++++++++++++++++ src/assets/images/chiken.png | Bin 0 -> 58039 bytes src/assets/images/login-bg.png | Bin 0 -> 283614 bytes src/assets/images/logo.png | Bin 0 -> 8082 bytes src/assets/images/mandefault.png | Bin 0 -> 5711 bytes src/assets/images/womandefault.png | Bin 0 -> 5579 bytes src/assets/img404/bg404.jpg | Bin 0 -> 36647 bytes src/assets/img404/i404.png | Bin 0 -> 17165 bytes src/assets/img404/sign.png | Bin 0 -> 433534 bytes src/assets/lang.png | Bin 0 -> 6200 bytes src/components/ECharts/lineEcharts.vue | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/components/lang/langSelect.vue | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/components/userForm/editPassword.vue | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/components/userForm/userInfo.vue | 278 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/config/index.js | 14 ++++++++++++++ src/directive/permission/button.js | 24 ++++++++++++++++++++++++ src/i18n/i18n.js | 13 +++++++++++++ src/i18n/lang/cn.js | 34 ++++++++++++++++++++++++++++++++++ src/i18n/lang/en.js | 33 +++++++++++++++++++++++++++++++++ src/i18n/lang/index.js | 6 ++++++ src/router/index.js | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/router/permission.js | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/store/index.js | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/store/modules/layout/index.js | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/store/modules/role.js | 32 ++++++++++++++++++++++++++++++++ src/store/modules/routerData.js | 40 ++++++++++++++++++++++++++++++++++++++++ src/utils/global.js | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/utils/index.js | 230 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/utils/rules.js | 461 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/views/commerViews.vue | 15 +++++++++++++++ src/views/duoji/erji.vue | 15 +++++++++++++++ src/views/duoji/sanji.vue | 15 +++++++++++++++ src/views/duoji/siji.vue | 15 +++++++++++++++ src/views/index/mainIndex.vue | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/views/layout/Footer/bottom.vue | 21 +++++++++++++++++++++ src/views/layout/aside/aside.vue | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/views/layout/aside/menuTree.vue | 29 +++++++++++++++++++++++++++++ src/views/layout/header/header.vue | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/views/layout/header/tabNav.vue | 219 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/views/layout/layout.vue | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/views/login/index.vue | 264 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/views/page404.vue | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/views/systemManage/roleManage.vue | 283 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 50 files changed, 3644 insertions(+), 0 deletions(-) create mode 100644 src/api/apis/login.js create mode 100644 src/api/apis/role.js create mode 100644 src/api/apis/user.js create mode 100644 src/api/axios.js create mode 100644 src/api/index.js create mode 100644 src/api/urls/login.js create mode 100644 src/api/urls/role.js create mode 100644 src/api/urls/user.js create mode 100644 src/assets/images/chiken.png create mode 100644 src/assets/images/login-bg.png create mode 100644 src/assets/images/logo.png create mode 100644 src/assets/images/mandefault.png create mode 100644 src/assets/images/womandefault.png create mode 100644 src/assets/img404/bg404.jpg create mode 100644 src/assets/img404/i404.png create mode 100644 src/assets/img404/sign.png create mode 100644 src/assets/lang.png create mode 100644 src/components/ECharts/lineEcharts.vue create mode 100644 src/components/lang/langSelect.vue create mode 100644 src/components/userForm/editPassword.vue create mode 100644 src/components/userForm/userInfo.vue create mode 100644 src/config/index.js create mode 100644 src/directive/permission/button.js create mode 100644 src/i18n/i18n.js create mode 100644 src/i18n/lang/cn.js create mode 100644 src/i18n/lang/en.js create mode 100644 src/i18n/lang/index.js create mode 100755 src/router/index.js create mode 100644 src/router/permission.js create mode 100644 src/store/index.js create mode 100644 src/store/modules/layout/index.js create mode 100644 src/store/modules/role.js create mode 100644 src/store/modules/routerData.js create mode 100644 src/utils/global.js create mode 100644 src/utils/index.js create mode 100644 src/utils/rules.js create mode 100644 src/views/commerViews.vue create mode 100644 src/views/duoji/erji.vue create mode 100644 src/views/duoji/sanji.vue create mode 100644 src/views/duoji/siji.vue create mode 100644 src/views/index/mainIndex.vue create mode 100644 src/views/layout/Footer/bottom.vue create mode 100644 src/views/layout/aside/aside.vue create mode 100644 src/views/layout/aside/menuTree.vue create mode 100644 src/views/layout/header/header.vue create mode 100644 src/views/layout/header/tabNav.vue create mode 100644 src/views/layout/layout.vue create mode 100644 src/views/login/index.vue create mode 100644 src/views/page404.vue create mode 100644 src/views/systemManage/roleManage.vue diff --git a/src/api/apis/login.js b/src/api/apis/login.js new file mode 100644 index 0000000..930141b --- /dev/null +++ b/src/api/apis/login.js @@ -0,0 +1,10 @@ + +import axios from "../axios" +import loginUrls from "../urls/login" + +export default { + // 账号密码登陆 + fetchLogin (data) { + return axios.post(loginUrls.login, data) + } +} diff --git a/src/api/apis/role.js b/src/api/apis/role.js new file mode 100644 index 0000000..71e6782 --- /dev/null +++ b/src/api/apis/role.js @@ -0,0 +1,23 @@ + +import axios from "../axios" +import roleUrls from "../urls/role" + +export default { + // 获取权限列表 + fetchGetRoleList () { + return axios.post(roleUrls.getRoleList) + }, + // 增加角色 + fetchAddRole (data) { + return axios.post(roleUrls.addRole, data) + }, + // 删除角色 + fetchDelRole (data) { + return axios.post(roleUrls.delRole, data) + }, + // 分配角色权限 + fetchRolePermissions (data) { + return axios.post(roleUrls.rolePermissions, data) + } +} + diff --git a/src/api/apis/user.js b/src/api/apis/user.js new file mode 100644 index 0000000..d1483cc --- /dev/null +++ b/src/api/apis/user.js @@ -0,0 +1,35 @@ + +import axios from "../axios" +import userUrls from "../urls/user" + +export default { + // 注册/添加账号 + fetchRegister (data) { + return axios.post(userUrls.register, data) + }, + // 删除用户 + fetchDelUser (data) { + return axios.post(userUrls.delUser, data) + }, + // 获取用户列表 + fetchUserList (data) { + return axios.post(userUrls.userList, data) + }, + // 修改用户信息 + fetchEditUser (data) { + return axios.post(userUrls.editUser, data) + }, + // 获取当前用户信息 + fetchGetUserInfo () { + return axios.get(userUrls.getUserInfo) + }, + // 获取用户信息 + fetchGetUserInfoId (data) { + return axios.post(userUrls.getUserInfoId, data) + }, + // 修改密码 + fetchEditPassword (data) { + return axios.post(userUrls.editPassword, data) + } +} + diff --git a/src/api/axios.js b/src/api/axios.js new file mode 100644 index 0000000..384ce91 --- /dev/null +++ b/src/api/axios.js @@ -0,0 +1,57 @@ +import axios from "axios" +import Cookies from "js-cookie" +import NProgress from "nprogress" +import { Message } from "element-ui" +// axios默认配置 +axios.defaults.timeout = 10000 // 超时时间 +axios.defaults.baseURL = process.env.API_HOST + +// http request 拦截器 +axios.interceptors.request.use(config => { + NProgress.start() + config.headers["Content-Type"] = "application/json;charset=UTF-8" + if (Cookies.get("access_token")) { + config.headers.Authorization = "Bearer" + Cookies.get("access_token") + } + return config +}, +error => { + return Promise.reject(error.response) +}) + +// http response 拦截器 +axios.interceptors.response.use( + response => { + NProgress.done() + if (response.data.code === 11000) { + Cookies.set("access_token", response.data.message, { expires: 1 / 12 }) + return Promise.resolve() + } else if (response.data.code === 10000) { // 约定报错信息 + Message({ + message: response.data.message, + type: "warning" + }) + return Promise.reject(response) + } else { + return Promise.resolve(response) + } + }, + error => { + if (error.response.status === 404) { + Message({ + message: "请求地址出错", + type: "warning" + }) + } else if (error.response.status === 401) { + Message({ + message: error.response.data.message, + type: "warning" + }) + Cookies.remove("access_token") + setTimeout(() => { + location.reload() + }, 3000) + } + return Promise.reject(error.response) // 返回接口返回的错误信息 + }) +export default axios diff --git a/src/api/index.js b/src/api/index.js new file mode 100644 index 0000000..ce6c9b3 --- /dev/null +++ b/src/api/index.js @@ -0,0 +1,8 @@ +const modulesFiles = require.context("./apis", true, /\.js$/) +const modules = modulesFiles.keys().reduce((modules, modulePath) => { + const value = modulesFiles(modulePath) + modules = Object.assign(modules, value.default) + return modules +}, {}) + +export default modules diff --git a/src/api/urls/login.js b/src/api/urls/login.js new file mode 100644 index 0000000..1b687d9 --- /dev/null +++ b/src/api/urls/login.js @@ -0,0 +1,5 @@ + +export default { + // 账号密码登陆 + login: "/admin/user/login" +} diff --git a/src/api/urls/role.js b/src/api/urls/role.js new file mode 100644 index 0000000..3c971c0 --- /dev/null +++ b/src/api/urls/role.js @@ -0,0 +1,12 @@ + +export default { + // 获取角色列表 + getRoleList: "/permissions/getRoleList", + // 增加角色 + addRole: "/permissions/addRole", + // 删除角色 + delRole: "/permissions/delRole", + // 分配角色权限 + rolePermissions: "/permissions/rolePermissions" +} + diff --git a/src/api/urls/user.js b/src/api/urls/user.js new file mode 100644 index 0000000..fa3ea4f --- /dev/null +++ b/src/api/urls/user.js @@ -0,0 +1,17 @@ + +export default { + // 注册/添加账号 + register: "/admin/user/register", + // 删除用户 + delUser: "/user/delUser", + // 修改用户信息 + editUser: "/user/editUserInfo", + // 获取当前用户信息 + getUserInfo: "/user/getUserInfo", + // 获取用户信息 + getUserInfoId: "/user/getUserInfoId", + // 获取用户列表 + userList: "/user/userList", + // 修改密码 + editPassword: "/user/editPassword" +} diff --git a/src/assets/images/chiken.png b/src/assets/images/chiken.png new file mode 100644 index 0000000..c042339 Binary files /dev/null and b/src/assets/images/chiken.png differ diff --git a/src/assets/images/login-bg.png b/src/assets/images/login-bg.png new file mode 100644 index 0000000..716da84 Binary files /dev/null and b/src/assets/images/login-bg.png differ diff --git a/src/assets/images/logo.png b/src/assets/images/logo.png new file mode 100644 index 0000000..cfc0a3c Binary files /dev/null and b/src/assets/images/logo.png differ diff --git a/src/assets/images/mandefault.png b/src/assets/images/mandefault.png new file mode 100644 index 0000000..2d765c5 Binary files /dev/null and b/src/assets/images/mandefault.png differ diff --git a/src/assets/images/womandefault.png b/src/assets/images/womandefault.png new file mode 100644 index 0000000..fbf0697 Binary files /dev/null and b/src/assets/images/womandefault.png differ diff --git a/src/assets/img404/bg404.jpg b/src/assets/img404/bg404.jpg new file mode 100644 index 0000000..95e4bde Binary files /dev/null and b/src/assets/img404/bg404.jpg differ diff --git a/src/assets/img404/i404.png b/src/assets/img404/i404.png new file mode 100644 index 0000000..52a430a Binary files /dev/null and b/src/assets/img404/i404.png differ diff --git a/src/assets/img404/sign.png b/src/assets/img404/sign.png new file mode 100644 index 0000000..cb8333b Binary files /dev/null and b/src/assets/img404/sign.png differ diff --git a/src/assets/lang.png b/src/assets/lang.png new file mode 100644 index 0000000..23fb8a2 Binary files /dev/null and b/src/assets/lang.png differ diff --git a/src/components/ECharts/lineEcharts.vue b/src/components/ECharts/lineEcharts.vue new file mode 100644 index 0000000..173da34 --- /dev/null +++ b/src/components/ECharts/lineEcharts.vue @@ -0,0 +1,106 @@ + + + + + diff --git a/src/components/lang/langSelect.vue b/src/components/lang/langSelect.vue new file mode 100644 index 0000000..7cd2d7c --- /dev/null +++ b/src/components/lang/langSelect.vue @@ -0,0 +1,53 @@ + + + + + diff --git a/src/components/userForm/editPassword.vue b/src/components/userForm/editPassword.vue new file mode 100644 index 0000000..33c6577 --- /dev/null +++ b/src/components/userForm/editPassword.vue @@ -0,0 +1,130 @@ + + + + + diff --git a/src/components/userForm/userInfo.vue b/src/components/userForm/userInfo.vue new file mode 100644 index 0000000..c6467cb --- /dev/null +++ b/src/components/userForm/userInfo.vue @@ -0,0 +1,278 @@ + + + + diff --git a/src/config/index.js b/src/config/index.js new file mode 100644 index 0000000..5815dbc --- /dev/null +++ b/src/config/index.js @@ -0,0 +1,14 @@ +const modeUrl = { + // 开发环境 + development: { + baseURL: "/", + authBaseURL: "", + $cdn:"" + }, + // 生产环境 + production: { + authBaseURL: "", + $cdn:"" + }, +}; +module.exports = modeUrl[process.env.NODE_ENV] diff --git a/src/directive/permission/button.js b/src/directive/permission/button.js new file mode 100644 index 0000000..bf4551e --- /dev/null +++ b/src/directive/permission/button.js @@ -0,0 +1,24 @@ +export default { + install (Vue, options) { + Vue.directive("roleBtn", { + componentUpdated: function (el, binding) { + let roleArr = binding.value + let userRole = JSON.parse(localStorage.getItem("info")).role + if (roleArr && roleArr.indexOf(userRole) !== -1) { + return false + } else { + el.parentNode.removeChild(el) + } + }, + inserted: function (el, binding) { + let roleArr = binding.value + let userRole = JSON.parse(localStorage.getItem("info")).role + if (roleArr && roleArr.indexOf(userRole) !== -1) { + return false + } else { + el.parentNode.removeChild(el) + } + } + }) + } +} \ No newline at end of file diff --git a/src/i18n/i18n.js b/src/i18n/i18n.js new file mode 100644 index 0000000..ef75be5 --- /dev/null +++ b/src/i18n/i18n.js @@ -0,0 +1,13 @@ +import Vue from "vue" +import locale from "element-ui/lib/locale" +import VueI18n from "vue-i18n" +import messages from "./lang" + +Vue.use(VueI18n) +const i18n = new VueI18n({ + locale: localStorage.lang || "cn", + messages +}) +locale.i18n((key, value) => i18n.t(key, value)) + +export default i18n diff --git a/src/i18n/lang/cn.js b/src/i18n/lang/cn.js new file mode 100644 index 0000000..1dbbe0a --- /dev/null +++ b/src/i18n/lang/cn.js @@ -0,0 +1,34 @@ + +import zhLocale from "element-ui/lib/locale/lang/zh-CN" +const cn = { + routeName: { + home: "主页", + icon: "图标", + builtInIcon: "内置图标", + permissions: "权限管理", + multiDirectory: "多级目录", + "menu2-1": "二级-1", + "menu2-3": "二级-3", + "menu3-1": "三级-1", + "menu4-1": "四级-1", + }, + rightMenu: { + close: "关闭", + closeOther: "关闭其他", + closeAll: "全部关闭" + }, + role: { + superAdmin: "超级管理员", + admin: "管理员", + ordinary: "普通用户" + }, + userDropdownMenu: { + basicInfor: "基本资料", + changePassword: "修改密码", + logout: "退出" + }, + + ...zhLocale // 合并element-ui内置翻译 +} + +export default cn diff --git a/src/i18n/lang/en.js b/src/i18n/lang/en.js new file mode 100644 index 0000000..478e48f --- /dev/null +++ b/src/i18n/lang/en.js @@ -0,0 +1,33 @@ +import enLocale from "element-ui/lib/locale/lang/en" +const en = { + routeName: { + home: "home", + icon: "icon", + builtInIcon: "builtInIcon", + permissions: "permissions", + multiDirectory: "multiDirectory", + "menu2-1": "menu2-1", + "menu2-3": "menu2-3", + "menu3-1": "menu3-1", + "menu4-1": "menu4-1", + }, + rightMenu: { + close: "close", + closeOther: "closeOther", + closeAll: "closeAll" + }, + role: { + superAdmin: "superAdmin", + admin: "admin", + ordinary: "ordinary" + }, + userDropdownMenu: { + basicInfor: "basicInfor", + changePassword: "changePassword", + logout: "logout" + }, + + ...enLocale // 合并element-ui内置翻译 +} + +export default en diff --git a/src/i18n/lang/index.js b/src/i18n/lang/index.js new file mode 100644 index 0000000..bad633f --- /dev/null +++ b/src/i18n/lang/index.js @@ -0,0 +1,6 @@ +import en from "./en" +import cn from "./cn" +export default { + en, + cn +} diff --git a/src/router/index.js b/src/router/index.js new file mode 100755 index 0000000..dec8e9a --- /dev/null +++ b/src/router/index.js @@ -0,0 +1,61 @@ +import en from "../i18n/lang/en" +import Vue from "vue" +import Router from "vue-router" +import Login from "@/views/login/index" +import Layout from "@/views/layout/layout" +import HomeMain from "@/views/index/mainIndex" + +// 不是必须加载的组件使用懒加载 +const NotFound = () => import("@/views/page404") + +/** + * 重写路由的push方法 + */ +const routerPush = Router.prototype.push +Router.prototype.push = function push (location) { + return routerPush.call(this, location).catch(error => error) +} +Vue.use(Router) +let routeName = en.routeName +let defaultRouter = [ + { path: "/", + redirect: "/index", + hidden: true, + children: [] + }, + { + path: "/login", + component: Login, + name: "登录", + hidden: true, + children: [] + }, + { + path: "/index", + iconCls: "fa fa-dashboard", // 图标样式class + name: "首页", + component: Layout, + alone: true, + children: [ + { + path: "/index", + iconCls: "fa fa-dashboard", // 图标样式class + name: "主页", + component: HomeMain, + children: [] + } + ] + }, + { + path: "/404", + component: NotFound, + name: "404", + hidden: true, + children: [] + } +] + +export default new Router({ + routes: defaultRouter +}) +export {defaultRouter} diff --git a/src/router/permission.js b/src/router/permission.js new file mode 100644 index 0000000..d93fbd7 --- /dev/null +++ b/src/router/permission.js @@ -0,0 +1,143 @@ +import NProgress from "nprogress" +import en from "../i18n/lang/en" +import Layout from "@/views/layout/layout" +import CommerViews from "@/views/commerViews" +import router from "./index" +import store from "../store" +let routeName = en.routeName + +const Erji = () => import("@/views/duoji/erji") +const Sanji = () => import("@/views/duoji/sanji") + let addrouters = [ //测试用,后续后端获取 + + { + path: "/", + iconCls: "fa fa-server", + // name: routeName.multiDirectory, + name: '多级', + component: Layout, + children: [ + { + path: "/erji1", + iconCls: "fa fa-server", + // name: routeName["menu2-1"], + name: '二级', + component: Erji, + meta:{ + role:['admin'] + }, + children: [] + }, + { + path: "/erji3", + iconCls: "fa fa-server", + name: "三级", + component: CommerViews, // 无限极菜单的容器 + children: [ + { + path: "/sanji1", + iconCls: "fa fa-server", + name: "三级子页面", + component: Sanji, + children: [] + }, + ] + } + ] + }, + + { path: "*", + redirect: "/404", + hidden: true, + children: [] + } +] + + +// 获取角色信息,根据用户权限动态加载路由 +router.beforeEach((to, from, next) => { + NProgress.start() + if (store.getters.token) { + if (to.path === "/login") { + next({path: "/"}) + } else { + if (!store.getters.info.role) { + !(async function getAddRouters () { + // 省略 axios 请求代码 通过 token 向后台请求用户权限等信息,这里用假数据赋值 + await store.dispatch("setInfo", { + role: "superAdmin", + permissions: "超级管理员", + name:"张老师", + }) + await store.dispatch("newRoutes",addrouters) + let newAddRouters = store.getters.addRouters + await router.addRoutes(newAddRouters) + next({path: to.path}) + }()) + } else { + let is404 = to.matched.some(record => { + if (record.meta.role) { + return store.getters.info.authorityRouter === -1 + } + }) + if (is404) { + next({path: "/404"}) + return false + } + next() + } + } + } else { + if (to.path === "/login") { + next() + } + next({path: "/login"}) + } +}) + +router.afterEach(() => { + NProgress.done() +}) + + +// // 真实使用 +// import fetchUser from "@/api/apis/user" +// +// router.beforeEach((to, from, next) => { +// if (store.getters.token && store.getters.token !== "undefined") { +// // store.dispatch('setToken', store.getters.token) +// if (to.path === "/login") { +// next({path: "/"}) +// } else { +// if (!store.getters.info) { +// (async function getAddRouters () { +// fetchUser.fetchGetUserInfo().then(async function (response) { +// await store.dispatch("setInfo", response.data) + // await store.dispatch("newRoutes", store.getters.info.authorityRouter) +// await router.addRoutes(store.getters.addRouters) +// next({path: "/index"}) +// }).catch(function (error) { +// console.log(error) +// }) +// }()) +// } else { +// let is404 = to.matched.some(record => { +// console.log(record) +// if (record.meta.role) { +// return store.getters.info.authorityRouter === -1 +// } +// }) +// if (is404) { +// next({path: "/404"}) +// return false +// } +// next() +// } +// } +// } else { +// if (to.path === "/login") { +// next() +// } +// next({path: "/login"}) +// } +// }) diff --git a/src/store/index.js b/src/store/index.js new file mode 100644 index 0000000..de0206f --- /dev/null +++ b/src/store/index.js @@ -0,0 +1,46 @@ +import Vue from "vue" +import Vuex from "vuex" +import Cookies from "js-cookie" +import routerData from "./modules/routerData" +import role from "./modules/role" +import layout from "./modules/layout/index" + +Vue.use(Vuex) + +const store = new Vuex.Store({ + state: { + token: Cookies.get("token") + }, + mutations: { + setToken (state, token) { + state.token = token + Cookies.set("token", token, { expires: 1 / 24 }) + } + }, + actions: { + setToken ({commit}, token) { + return new Promise((resolve, reject) => { + commit("setToken", token) + resolve() + }) + } + }, + getters: { + addRouters: state => state.routerData.addRouters, + token: state => state.token, + info: state => state.role.info, + routers: state => state.routerData.routers, + logoShow: state => state.layout.logoShow, + isCollapse: state => state.layout.isCollapse, + uniquerouter: state => state.layout.uniquerouter, + tabnavBox: state => state.layout.tabnavBox, + rightNav: state => state.layout.rightNav + }, + modules: { + routerData, + role, + layout + } +}) + +export default store diff --git a/src/store/modules/layout/index.js b/src/store/modules/layout/index.js new file mode 100644 index 0000000..f6d67d8 --- /dev/null +++ b/src/store/modules/layout/index.js @@ -0,0 +1,90 @@ + +export default { + state: { + isCollapse: false, + logoShow: false, + uniquerouter: true, + rightNav: {}, + tabnavBox: JSON.parse(sessionStorage.getItem("addTab")) || [{ + title: "home", + path: "/index" + }] + }, + mutations: { + addTab (state, arg) { + state.isActive = arg.path + if (state.tabnavBox[0] && state.tabnavBox[0].title !== "home") { + state.tabnavBox.unshift({ + title: "home", + path: "/index" + }) + } + + for (let i = 0; i < state.tabnavBox.length; i++) { + if (state.tabnavBox[i].path === arg.path) { + return false + } + } + state.tabnavBox.push({ + title: arg.title, + path: arg.path + }) + + sessionStorage.setItem("addTab", JSON.stringify(state.tabnavBox)) + }, + openMenu (state, arg) { + state.rightNav = arg + }, + removeTab (state, arg) { + let index = state.tabnavBox.findIndex(function (value, key) { + return value.path === arg.tabItem.path + }) + state.tabnavBox.splice(index, 1) + if (arg.tabItem.path === arg.fullPath) { + let tabActive = state.tabnavBox[index] || state.tabnavBox[index - 1] + arg.router.push(tabActive.path) + } + sessionStorage.setItem("addTab", JSON.stringify(state.tabnavBox)) + }, + removeOtherTab (state, arg) { + state.tabnavBox = [{ + title: "home", + path: "/index" + }] + if (arg.all) { + arg.router.push("/index") + return false + } + state.tabnavBox.push(arg.tabItem) + arg.router.push(arg.tabItem.path) + sessionStorage.setItem("addTab", JSON.stringify(state.tabnavBox)) + }, + collapse (state, arg) { + state.isCollapse = !state.isCollapse + if (state.logoShow) { + setTimeout(function () { + state.logoShow = false + }, 300) + } else { + state.logoShow = true + } + } + }, + actions: { + addTab ({commit}, arg) { + commit("addTab", arg) + }, + openMenu ({commit}, arg) { + commit("openMenu", arg) + }, + removeTab ({commit}, arg) { + commit("removeTab", arg) + }, + removeOtherTab ({commit}, arg) { + commit("removeOtherTab", arg) + }, + collapse ({commit}, arg) { + commit("collapse", arg) + } + } +} diff --git a/src/store/modules/role.js b/src/store/modules/role.js new file mode 100644 index 0000000..ccfdc55 --- /dev/null +++ b/src/store/modules/role.js @@ -0,0 +1,32 @@ +import store from "../index" +import router from "../../router/index" +export default { + state: { + info: "" // 每次刷新都要通过token请求个人信息来筛选动态路由 + }, + mutations: { + setInfo (state, data) { + if (data.authorityRouter) { + data.authorityRouter = data.authorityRouter.indexOf(",") !== -1 ? data.authorityRouter.split(",") : new Array(data.authorityRouter) + } else { + data.authorityRouter = [] + } + + + + state.info = { + role: data.role, + name: data.name, + authorityRouter: data.authorityRouter, + avatar: data.avatar ? data.avatar : "", + uid: data.id + } + localStorage.setItem("info", JSON.stringify(store.getters.info)) + } + }, + actions: { + setInfo ({commit}, data) { + commit("setInfo", data) + } + } +} diff --git a/src/store/modules/routerData.js b/src/store/modules/routerData.js new file mode 100644 index 0000000..01987c0 --- /dev/null +++ b/src/store/modules/routerData.js @@ -0,0 +1,40 @@ +import {defaultRouter} from "@/router/index" + +const routerData = { + state: { + routers: [], + addRouters: [], + }, + mutations: { + setRouters: (state, routers) => { + state.addRouters = routers // 保存动态路由用来addRouter + state.routers = defaultRouter.concat(routers) // 所有有权限的路由表,用来生成菜单列表 + }, + }, + actions: { + newRoutes ({commit},addRouter) { + // 通过递归路由表,删除掉没有权限的路由 + function eachSelect (routers) { + for (let i = 0; i < routers.length; i++) { + if (routers[i].meta && routers[i].meta.role.length && routers[i].meta.role.indexOf(userRole) === -1) { + routers.splice(i, 1) + i = i !== 0 ? i - 1 : i + } + if (routers[i].children && routers[i].children.length) { + eachSelect(routers[i].children, userRole) + } + } + } + // 仅限演示 + let newArr = [...addRouter] // 拷贝这个数组是因为做权限测试的时候可以从低级切回到高级角色,仅限演示,正式开发时省略这步直接使用 addRouter + // eachSelect(newArr) + commit("setRouters", newArr) + + // 正式开发 + // eachSelect(addRouter, role) + // commit('setRouters', addRouter) + } + } +} + +export default routerData diff --git a/src/utils/global.js b/src/utils/global.js new file mode 100644 index 0000000..209ff0b --- /dev/null +++ b/src/utils/global.js @@ -0,0 +1,104 @@ +import rules from "./rules" +import request from "@/api" +import * as echarts from "echarts" + +export default { + install (Vue, options) { + Vue.prototype.$echarts = echarts + Vue.prototype.$request = request + Vue.prototype.$rules = rules + /** 时间字符串 + * @method $getDateDiff + * @param timespan + */ + Vue.prototype.$getDateDiff = function (timespan) { + var dateTime = new Date(timespan) + var year = dateTime.getFullYear() + var month = (dateTime.getMonth() + 1) < 10 ? "0" + (dateTime.getMonth() + 1) : (dateTime.getMonth() + 1) + var day = dateTime.getDate() < 10 ? "0" + dateTime.getDate() : dateTime.getDate() + var hour = dateTime.getHours() < 10 ? "0" + dateTime.getHours() : dateTime.getHours() + var minute = dateTime.getMinutes() < 10 ? "0" + dateTime.getMinutes() : dateTime.getMinutes() + var seconds = dateTime.getSeconds() < 10 ? "0" + dateTime.getSeconds() : dateTime.getSeconds() + var now = new Date() + var nowNew = now.getTime() + var milliseconds = 0 + var timeSpanStr + milliseconds = nowNew - dateTime + + if (milliseconds <= 1000 * 60 * 1) { + timeSpanStr = "刚刚" + } else if (1000 * 60 * 1 < milliseconds && milliseconds <= 1000 * 60 * 60) { + timeSpanStr = Math.round((milliseconds / (1000 * 60))) + "分钟前" + } else if (1000 * 60 * 60 * 1 < milliseconds && milliseconds <= 1000 * 60 * 60 * 24) { + timeSpanStr = Math.round(milliseconds / (1000 * 60 * 60)) + "小时前" + } else if (1000 * 60 * 60 * 24 < milliseconds && milliseconds <= 1000 * 60 * 60 * 24 * 3) { + timeSpanStr = Math.round(milliseconds / (1000 * 60 * 60 * 24)) + "天前" + } else if (milliseconds > 1000 * 60 * 60 * 24 * 3 && year === now.getFullYear()) { + timeSpanStr = month + "-" + day + " " + hour + ":" + minute + ":" + seconds + } else { + timeSpanStr = year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + seconds + } + return timeSpanStr + } + + /** 当前地址ip + * @method $path + * @param {} + */ + Vue.prototype.$path = process.env.API_HOST + + /** 传入路径转换成完整连接 + * @method $getPath + * @param {url: 路径} + */ + Vue.prototype.$getPath = function (url) { + const base = process.env.API_HOST + if (/^http/.test(url)) return url + return base + url + } + /** 是否开发模式 + * @method $env + * @param {} + */ + Vue.prototype.$env = process.env.NODE_ENV + + /** 导出,下载处理文件流 + * @method $exportClick + * @param {res:文件流,name : 下载文件名} + */ + Vue.prototype.$exportClick = function (res, name = "下载.zip") { + const content = res + const blob = new Blob([content]) + const fileName = name + if ("download" in document.createElement("a")) { // 非IE下载 + const elink = document.createElement("a") + elink.download = fileName + elink.style.display = "none" + elink.href = URL.createObjectURL(blob) + document.body.appendChild(elink) + elink.click() + URL.revokeObjectURL(elink.href) // 释放URL 对象 + document.body.removeChild(elink) + } else { // IE10+下载 + navigator.msSaveBlob(blob, fileName) + } + } + + /** 当res.code === 200 时 + * @method $restBack + * @param res + * @param fn + * @param message + * @param type + */ + Vue.prototype.$restBack = function (res, fn = () => {}, message, type = "success") { + if (res.code === 200) { + this.$message({ + message: message || res.message, + type: type + }) + fn() + } + } + } +} diff --git a/src/utils/index.js b/src/utils/index.js new file mode 100644 index 0000000..9cab787 --- /dev/null +++ b/src/utils/index.js @@ -0,0 +1,230 @@ + +import CryptoJS from "crypto-js" + +const encryptKey = "WfJTKO9S4eLkrPz2JKrAnzdb" +const encryptIV = "D076D35C" + +// 深度复制 +export function deepClone (obj) { + let result = Array.isArray(obj) ? [] : {} + for (let key in obj) { + if (obj.hasOwnProperty(key)) { + if (typeof obj[key] === "object") { + result[key] = deepClone(obj[key]) + } else { + result[key] = obj[key] + } + } + } + return result +} + +// 3DES加密 +export function desEncrypt (str, key = encryptKey, iv = encryptIV) { + var cryptoKey = CryptoJS.enc.Utf8.parse(key) + var cryptoIv = CryptoJS.enc.Utf8.parse(iv.substr(0, 8)) + var encodeStr = CryptoJS.TripleDES.encrypt(str, cryptoKey, { + iv: cryptoIv, + mode: CryptoJS.mode.CBC, + padding: CryptoJS.pad.Pkcs7 + }) + return encodeStr.toString() +} + +// 3DES解密 +export function desDecrypt (str, key = encryptKey, iv = encryptIV) { + var cryptoKey = CryptoJS.enc.Utf8.parse(key) + var cryptoIv = CryptoJS.enc.Utf8.parse(iv.substr(0, 8)) + var decryptStr = CryptoJS.TripleDES.decrypt(str, cryptoKey, { + iv: cryptoIv, + mode: CryptoJS.mode.CBC, + padding: CryptoJS.pad.Pkcs7 + }) + return decryptStr.toString(CryptoJS.enc.Utf8) +} + +// 随机生成由字母+数字的字符串 +export function randomWord (randomFlag, min, max) { + // randomFlag: Boolean 是否随机个数 + // min 最少个数 + // max 最大个数 + var str = "" + var range = min + var arr = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"] + // 随机产生 + if (randomFlag) { + range = Math.round(Math.random() * (max - min)) + min + } + var pos = "" + for (var i = 0; i < range; i++) { + pos = Math.round(Math.random() * (arr.length - 1)) + str += arr[pos] + } + return str +} + +// 判断数组中是否存在相同值 +export function hasRepeatValue (arr, key = null) { + if (key) arr = arr.map(d => d[key]) + if (arr.length) { + let nameNum = arr.reduce((pre, cur) => { + if (cur in pre) { + pre[cur]++ + } else { + pre[cur] = 1 + } + return pre + }, {}) + return Object.values(nameNum).findIndex(d => d > 1) < 0 + } + return true +} + +// 获取cookie值 +export function getCookie (name, defaultValue) { + const result = new RegExp("(^| )" + name + "=([^;]*)(;|$)") + return result[0] === document.cookie.match(result[1]) ? unescape(result[0][2]) : defaultValue +} + +// base64ToFile +export function base64ToFile (base64Data, tempfilename, contentType) { + contentType = contentType || "" + var sliceSize = 1024 + var byteCharacters = atob(base64Data) + var bytesLength = byteCharacters.length + var slicesCount = Math.ceil(bytesLength / sliceSize) + var byteArrays = new Array(slicesCount) + + for (var sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) { + var begin = sliceIndex * sliceSize + var end = Math.min(begin + sliceSize, bytesLength) + + var bytes = new Array(end - begin) + for (var offset = begin, i = 0; offset < end; ++i, ++offset) { + bytes[i] = byteCharacters[offset].charCodeAt(0) + } + byteArrays[sliceIndex] = new Uint8Array(bytes) + } + var file = new File(byteArrays, tempfilename, { type: contentType }) + return file +} + +// 将base64转换为文件 +export function dataURLtoFile (dataurl, filename) { + var arr = dataurl.split(",") + var mime = arr[0].match(/:(.*?);/)[1] + var bstr = atob(arr[1]) + var n = bstr.length + var u8arr = new Uint8Array(n) + while (n--) { + u8arr[n] = bstr.charCodeAt(n) + } + return new File([u8arr], filename, { type: mime }) +} + +// 将图片转换为Base64 +export function getImgToBase64 (url, callback, outputFormat) { + var canvas = document.createElement("canvas") + var ctx = canvas.getContext("2d") + var img = new Image() + img.crossOrigin = "Anonymous" + img.onload = function () { + canvas.height = img.height + canvas.width = img.width + ctx.drawImage(img, 0, 0) + var dataURL = canvas.toDataURL(outputFormat || "image/png") + callback(dataURL) + canvas = null + } + img.src = url +} + +// 转换级联下拉数据 +export function loopOptions (list, option = {}) { + option = { + value: "id", + label: "name", + children: "children", + ...option + } + if (list instanceof Array && list.length) { + return list.map((d, i) => { + d.value = d[option.value] || i + 1 + d.label = d[option.label] + if (d[option.children]) { + d[option.children] = loopOptions(d[option.children], option) + } + return d + }) + } + return [] +} + +// 通过Id获取级联数据id数组 +export function getTreeIds (tree, currentId, key = "id") { + let parent = {} + let pid = {} + const loop = (list, level) => { + if (list instanceof Array && list.length) { + for (let index = 0; index < list.length; index++) { + const d = list[index] + parent[level] = d.id + if (d[key] === currentId) { + for (let idx = 1; idx <= level; idx++) { + pid[idx] = parent[idx] + } + break + } else if (d.children) { + loop(d.children, level + 1) + } + } + } + } + loop(tree, 1) + let result = [] + Object.keys(pid).sort((a, b) => a - b).forEach(k => { + result.push(pid[k]) + }) + return result +} + +// 秒转换时分秒 +export function transverterMss (result) { + var h = Math.floor(result / 3600) < 10 ? "0" + Math.floor(result / 3600) : Math.floor(result / 3600) + var m = Math.floor((result / 60 % 60)) < 10 ? "0" + Math.floor((result / 60 % 60)) : Math.floor((result / 60 % 60)) + var s = Math.floor((result % 60)) < 10 ? "0" + Math.floor((result % 60)) : Math.floor((result % 60)) + return h + ":" + m + ":" + s +} + +// 获取日期时间戳 +export function getTime (dayNum) { + var myDate = new Date() + var lw = new Date(myDate - 1000 * 60 * 60 * 24 * dayNum)// 最后一个数字多少天前的意思 + var lastY = lw.getFullYear() + var lastM = lw.getMonth() + 1 + var lastD = lw.getDate() + var startdate = lastY + "-" + (lastM < 10 ? "0" + lastM : lastM) + "-" + (lastD < 10 ? "0" + lastD : lastD) + var b = startdate.split(/\D/) + var date = new Date(b[0], b[1] - 1, b[2]) + var time = date.getTime() + return time +} + +// 获取几天之前日期 +export function getData (dayNum) { + var myDate = new Date() + var lw = new Date(myDate - 1000 * 60 * 60 * 24 * dayNum)// 最后一个数字多少天前的意思 + var lastY = lw.getFullYear() + var lastM = lw.getMonth() + 1 + var lastD = lw.getDate() + var startdate = lastY + "-" + (lastM < 10 ? "0" + lastM : lastM) + "-" + (lastD < 10 ? "0" + lastD : lastD) + return startdate +} + +// 日期转换时间戳 +export function getNewTime (dayNum) { + var b = dayNum.split(/\D/) + var date = new Date(b[0], b[1] - 1, b[2]) + var time = date.getTime() + return time +} diff --git a/src/utils/rules.js b/src/utils/rules.js new file mode 100644 index 0000000..8919419 --- /dev/null +++ b/src/utils/rules.js @@ -0,0 +1,461 @@ +export default { + // 必选 + requiredSelect: (mes = "此项必选", trigger = ["blur", "change"]) => { + return { + required: true, + message: mes, + trigger: trigger + } + }, + // 固定长度 + $length: (len = 1, message = `长度必须为${len}`, trigger = ["blur", "change"]) => { + return { + len: len, + message: message, + trigger: trigger + } + }, + // 长度验证 + len: (min = 1, max = 255, message = `长度为${min}-${max}`, trigger = ["blur", "change"]) => { + return { + min: min, + max: max, + message: message, + trigger: trigger + } + }, + // 最小长度 + min: (min = 1, message = `最小长度为${min}`, trigger = ["blur", "change"]) => { + return { + min: min, + message: message, + trigger: trigger + } + }, + // 最大长度 + max: (max = 255, message = `最大长度为${max}`, trigger = ["blur", "change"]) => { + return { + max: max, + message: message, + trigger: trigger + } + }, + // 最小数 + minNum: (min = 1, type = "number", message = `不能小于${min}`, trigger = ["blur", "change"]) => { + return { + type: type, + min: min, + message: message, + trigger: trigger + } + }, + // 最大数 + maxNum: (max = 255, type = "number", message = `不能大于${max}`, trigger = ["blur", "change"]) => { + return { + type: type, + max: max, + message: message, + trigger: trigger + } + }, + // 数值范围 + rangeNum: (min = 1, max = 255, message = `只能输入${min}-${max}之间的数`, trigger = ["blur", "change"]) => { + const validator = (rule, value, callback) => { + if (value === "" || (Number(value) >= min && Number(value) <= max)) { + callback() + } else { + callback(new Error(message)) + } + } + return { + validator, + trigger + } + }, + // 类型 + type: (type = "string", message = `输入的类型必须为${type}`, trigger = ["blur", "change"]) => { + return { + type: type, + message: message, + trigger: trigger + } + }, + + password: (callback) => { + return { + validator: callback, + trigger: "change" + } + }, + // 邮箱 + email: (message = "请输入正确的邮箱地址", trigger = ["blur", "change"]) => { + // eslint-disable-next-line no-useless-escape + const reg = /^[a-zA-Z0-9][a-zA-Z0-9 . _-]+(@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)+)$/ + const validator = (rule, value, callback) => { + if (value === "" || reg.test(value)) { + callback() + } else { + callback(new Error(message)) + } + } + return { + validator, + trigger + } + }, + // 大写字母 + upperCase: (message = "请输入大写字母", trigger = ["blur", "change"]) => { + const reg = /^[A-Z]+$/ + const validator = (rule, value, callback) => { + if (value === "" || reg.test(value)) { + callback() + } else { + callback(new Error(message)) + } + } + return { + validator, + trigger + } + }, + // 小写字母 + lowerCase: (message = "请输入小写字母", trigger = ["blur", "change"]) => { + const reg = /^[A-Z]+$/ + const validator = (rule, value, callback) => { + if (value === "" || reg.test(value)) { + callback() + } else { + callback(new Error(message)) + } + } + return { + validator, + trigger + } + }, + // 大小写字母 + english: (message = "请输入英文", trigger = ["blur", "change"]) => { + const reg = /^[A-Za-z]+$/ + const validator = (rule, value, callback) => { + if (value === "" || reg.test(value)) { + callback() + } else { + callback(new Error(message)) + } + } + return { + validator, + trigger + } + }, + // 只能输中文 + chinese: (message = "请输入中文", trigger = ["blur", "change"]) => { + const reg = /^[\u4e00-\u9fa5]+$/ + const validator = (rule, value, callback) => { + if (value === "" || reg.test(value)) { + callback() + } else { + callback(new Error(message)) + } + } + return { + validator, + trigger + } + }, + // 不能输中文 + noChinese: (message = "不能包含中文", trigger = ["blur", "change"]) => { + const validator = (rule, value, callback) => { + if (value === "" || escape(value).indexOf("%u") >= 0) { + callback() + } else { + callback(new Error(message)) + } + } + return { + validator, + trigger + } + }, + // 中文英文数字 + cnEnNum: (message = "请输入中文、大小写英文、数字", trigger = ["blur", "change"]) => { + const reg = /^[\u4e00-\u9fa5|A-Za-z0-9]+$/ + const validator = (rule, value, callback) => { + if (value === "" || reg.test(value)) { + callback() + } else { + callback(new Error(message)) + } + } + return { + validator, + trigger + } + }, + // 路径 + path: (message = "请输入英文、数字、划线、斜线", trigger = ["blur", "change"]) => { + const reg = /^[-|_|/|A-Za-z0-9]+$/ + const validator = (rule, value, callback) => { + if (value === "" || reg.test(value)) { + callback() + } else { + callback(new Error(message)) + } + } + return { + validator, + trigger + } + }, + // 英文数字下划线 + enNumLine: (message = "请输入英文、数字、下划线", trigger = ["blur", "change"]) => { + const reg = /^[_|A-Za-z0-9]+$/ + const validator = (rule, value, callback) => { + if (value === "" || reg.test(value)) { + callback() + } else { + callback(new Error(message)) + } + } + return { + validator, + trigger + } + }, + // 英文数字 + enNum: (message = "请输入英文、数字", trigger = ["blur", "change"]) => { + const reg = /^[A-Za-z0-9]+$/ + const validator = (rule, value, callback) => { + if (value === "" || reg.test(value)) { + callback() + } else { + callback(new Error(message)) + } + } + return { + validator, + trigger + } + }, + // 必须包含英文数字 + haveCnEnNum: (message = "必须包含英文和数字", trigger = ["blur", "change"]) => { + const reg = /^(?=.*[a-zA-Z]+)(?=.*[0-9]+)[a-zA-Z0-9]+$/ + const validator = (rule, value, callback) => { + if (value === "" || reg.test(value)) { + callback() + } else { + callback(new Error(message)) + } + } + return { + validator, + trigger + } + }, + // 手机号 + mobile: (message = "请输入正确的手机号码", trigger = ["blur", "change"]) => { // 手机号码验证 + const reg = /^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(16[2|6|7])|(18[0-9])|(17([0-1]|[3]|[5-8]))|(19[1|8|9]))\d{8}$/ + const validator = (rule, value, callback) => { + if (value === "" || reg.test(value)) { + callback() + } else { + callback(new Error(message)) + } + } + return { + validator, + trigger + } + }, + // 座机 + phone: (message = "请输入正确的座机号码", trigger = ["blur", "change"]) => { + const reg = /^((\d{3,4}-\d{7,8})|(\d{7}-\d{1,12})|(\d{8}-\d{1,11})|(\d{11}-\d{1,8})|(\d{7,8})|(\d{11,20})|(\d{3}-\d{8}-\d{1,7})|(\d{3}-\d{7}-\d{1,8})|(\d{4}-\d{7}-\d{1,7})|(\d{4}-\d{8}-\d{1,6}))$/ + const validator = (rule, value, callback) => { + if (value === "" || reg.test(value)) { + callback() + } else { + callback(new Error(message)) + } + } + return { + validator, + trigger + } + }, + // 手机或座机 + phoneAll: (message = "请输入正确的电话号码", trigger = ["blur", "change"]) => { + const reg = /^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(16[2|6|7])|(18[0-9])|(17([0-1]|[3]|[5-8]))|(19[1|8|9]))\d{8}$|^((\d{3,4}-\d{7,8})|(\d{7}-\d{1,12})|(\d{8}-\d{1,11})|(\d{11}-\d{1,8})|(\d{7,8})|(\d{11,20})|(\d{3}-\d{8}-\d{1,7})|(\d{3}-\d{7}-\d{1,8})|(\d{4}-\d{7}-\d{1,7})|(\d{4}-\d{8}-\d{1,6}))$/ + const validator = (rule, value, callback) => { + if (value === "" || reg.test(value)) { + callback() + } else { + callback(new Error(message)) + } + } + return { + validator, + trigger + } + }, + // 小数 + float: (message = "请输入合法的数字", trigger = ["blur", "change"]) => { + const reg = /^[0-9]+([.]{1}[0-9]+){0,1}$/ + const va = (rule, value, callback) => { + if (value === null || value === "") { + callback() + } + if (reg.test(value)) { + callback() + } else { + callback(new Error(message)) + } + } + return { + validator: va, + trigger: trigger + } + }, + // 两位小数 + decimal: (message = "请输入最多两位小数", trigger = ["blur", "change"]) => { + const reg = /^(([0-9]*)|(([0]\.\d{1,2}|[0-9]*\.\d{1,2})))$/ + const va = (rule, value, callback) => { + if (value === null || value === "") { + callback() + } + if (reg.test(value)) { + callback() + } else { + callback(new Error(message)) + } + } + return { + validator: va, + trigger: trigger + } + }, + // 整数 + number: (message = "请输入合法的数字", trigger = ["blur", "change"]) => { + const reg = /^[0-9]\d*$/ + const va = (rule, value, callback) => { + if (value === "") { + callback() + } else if (reg.test(value)) { + callback() + } else { + callback(new Error(message)) + } + } + return { + validator: va, + trigger: trigger + } + }, + // 正数 + plusNumber: (message = "请输入合法的数字", trigger = ["blur", "change"]) => { + const reg = /^(0|[1-9][0-9]*)(\.\d+)?$/ + const va = (rule, value, callback) => { + if (value === "") { + callback() + } else if (reg.test(value)) { + callback() + } else { + callback(new Error(message)) + } + } + return { + validator: va, + trigger: trigger + } + }, + // 大于0的正数 + moreThanZeroNumber: (message = "只能输入大于0的整数", trigger = ["blur", "change"]) => { + const reg = /^\+?[1-9]\d*$/ + const va = (rule, value, callback) => { + if (value === "") { + callback() + } else if (reg.test(value)) { + callback() + } else { + callback(new Error(message)) + } + } + return { + validator: va, + trigger: trigger + } + }, + // 网址 + url: (message = "请输入正确的网址", trigger = ["blur", "change"]) => { + const reg = /^(?=^.{3,255}$)(http(s)?:\/\/)?(www\.)?[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:\d+)*(\/\w+\.\w+)*$/ + const va = (rule, value, callback) => { + if (value === "") { + callback() + } + if (reg.test(value)) { + callback() + } else { + callback(new Error(message)) + } + } + return { + validator: va, + trigger: trigger + } + }, + // ip地址 + ip: (message = "请输入正确的ip", trigger = ["blur", "change"]) => { + const reg = /^(?=(\b|\D))(((\d{1,2})|(1\d{1,2})|(2[0-4]\d)|(25[0-5]))\.){3}((\d{1,2})|(1\d{1,2})|(2[0-4]\d)|(25[0-5]))(?=(\b|\D))*$/ + const va = (rule, value, callback) => { + if (value === "") { + callback() + } + if (reg.test(value)) { + callback() + } else { + callback(new Error(message)) + } + } + return { + validator: va, + trigger: trigger + } + }, + // 身份证号 + identity: (message = "请输入正确的身份证号", trigger = ["blur", "change"]) => { + const reg = /^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X|x)$/ + // ^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)|(^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{2}$ + const va = (rule, value, callback) => { + if (value === "") { + callback() + } + if (reg.test(value)) { + callback() + } else { + callback(new Error(message)) + } + } + return { + validator: va, + trigger: trigger + } + }, + // 邮政编码 + postal: (message = "请输入正确的邮政编码", trigger = ["blur", "change"]) => { + const reg = /^\d{6}$/ + const va = (rule, value, callback) => { + if (value === "") { + callback() + } + if (reg.test(value)) { + callback() + } else { + callback(new Error(message)) + } + } + return { + validator: va, + trigger: trigger + } + } +} + diff --git a/src/views/commerViews.vue b/src/views/commerViews.vue new file mode 100644 index 0000000..20c5912 --- /dev/null +++ b/src/views/commerViews.vue @@ -0,0 +1,15 @@ + + + + + diff --git a/src/views/duoji/erji.vue b/src/views/duoji/erji.vue new file mode 100644 index 0000000..ad9a4b1 --- /dev/null +++ b/src/views/duoji/erji.vue @@ -0,0 +1,15 @@ + + + + + diff --git a/src/views/duoji/sanji.vue b/src/views/duoji/sanji.vue new file mode 100644 index 0000000..96b82d0 --- /dev/null +++ b/src/views/duoji/sanji.vue @@ -0,0 +1,15 @@ + + + + + diff --git a/src/views/duoji/siji.vue b/src/views/duoji/siji.vue new file mode 100644 index 0000000..e2d114a --- /dev/null +++ b/src/views/duoji/siji.vue @@ -0,0 +1,15 @@ + + + + + diff --git a/src/views/index/mainIndex.vue b/src/views/index/mainIndex.vue new file mode 100644 index 0000000..0e5652e --- /dev/null +++ b/src/views/index/mainIndex.vue @@ -0,0 +1,147 @@ + + + + + diff --git a/src/views/layout/Footer/bottom.vue b/src/views/layout/Footer/bottom.vue new file mode 100644 index 0000000..7b281aa --- /dev/null +++ b/src/views/layout/Footer/bottom.vue @@ -0,0 +1,21 @@ + + + + + diff --git a/src/views/layout/aside/aside.vue b/src/views/layout/aside/aside.vue new file mode 100644 index 0000000..655b1c1 --- /dev/null +++ b/src/views/layout/aside/aside.vue @@ -0,0 +1,168 @@ + + + + + diff --git a/src/views/layout/aside/menuTree.vue b/src/views/layout/aside/menuTree.vue new file mode 100644 index 0000000..25bd60f --- /dev/null +++ b/src/views/layout/aside/menuTree.vue @@ -0,0 +1,29 @@ + + + + + diff --git a/src/views/layout/header/header.vue b/src/views/layout/header/header.vue new file mode 100644 index 0000000..ba089c0 --- /dev/null +++ b/src/views/layout/header/header.vue @@ -0,0 +1,183 @@ + + + + + diff --git a/src/views/layout/header/tabNav.vue b/src/views/layout/header/tabNav.vue new file mode 100644 index 0000000..3e564bd --- /dev/null +++ b/src/views/layout/header/tabNav.vue @@ -0,0 +1,219 @@ + + + + + diff --git a/src/views/layout/layout.vue b/src/views/layout/layout.vue new file mode 100644 index 0000000..351fce0 --- /dev/null +++ b/src/views/layout/layout.vue @@ -0,0 +1,133 @@ + + + + + + diff --git a/src/views/login/index.vue b/src/views/login/index.vue new file mode 100644 index 0000000..d268b21 --- /dev/null +++ b/src/views/login/index.vue @@ -0,0 +1,264 @@ + + + + diff --git a/src/views/page404.vue b/src/views/page404.vue new file mode 100644 index 0000000..25897ee --- /dev/null +++ b/src/views/page404.vue @@ -0,0 +1,72 @@ + + + + + diff --git a/src/views/systemManage/roleManage.vue b/src/views/systemManage/roleManage.vue new file mode 100644 index 0000000..379f9b1 --- /dev/null +++ b/src/views/systemManage/roleManage.vue @@ -0,0 +1,283 @@ + + + + + + -- libgit2 0.21.4