10 changed files with 453 additions and 15 deletions
			
			
		- 
					3src/components/ParentView/index.vue
- 
					0src/layout/index.vue
- 
					4src/main.js
- 
					94src/router/index.js
- 
					5src/router/routers.js
- 
					6src/settings.js
- 
					28src/store/modules/api.js
- 
					86src/store/modules/permission.js
- 
					2src/utils/request.js
- 
					240src/views/login.vue
| @ -0,0 +1,3 @@ | |||||
|  | <template> | ||||
|  |     <router-view/> | ||||
|  | </template> | ||||
| @ -0,0 +1,28 @@ | |||||
|  | //适配Nginx反向代理
 | ||||
|  | const baseUrl = process.env.VUE_APP_BASE_API === '/' ? '' : process.env.VUE_APP_BASE_API | ||||
|  | 
 | ||||
|  | //适配API路径
 | ||||
|  | const api = { | ||||
|  |   state: { | ||||
|  | 
 | ||||
|  |     //部署包上传
 | ||||
|  |     //deployUploadApi: baseUrl + '/api/deploy/upload',
 | ||||
|  | 
 | ||||
|  |     //图片上传
 | ||||
|  |     imagesUplaodApi: baseUrl + '/api/localStorage/pictures', | ||||
|  | 
 | ||||
|  |     //上传图像
 | ||||
|  |     updateAvatarApi: baseUrl + '/api/users/updateAvatar', | ||||
|  | 
 | ||||
|  |     //文件上传
 | ||||
|  |     fileUploadApi: baseUrl + '/api/localStorage', | ||||
|  | 
 | ||||
|  |     // swagger
 | ||||
|  |     swaggerApi: baseUrl + '/swagger-ui.html', | ||||
|  | 
 | ||||
|  |     //基础url
 | ||||
|  |     baseApi: baseUrl | ||||
|  |   } | ||||
|  | } | ||||
|  | 
 | ||||
|  | export default api | ||||
| @ -0,0 +1,86 @@ | |||||
|  | import { constantRouterMap } from "@/router/routers"; | ||||
|  | import Layout from '@/layout/index' | ||||
|  | import ParentView from '@/components/ParentView' | ||||
|  | 
 | ||||
|  | const permission = { | ||||
|  |   //存放状态
 | ||||
|  |   state: { | ||||
|  |     routers: constantRouterMap, | ||||
|  |     addRouters: [], | ||||
|  |     sidebarRouters: [] | ||||
|  |   }, | ||||
|  |   //同步更改状态
 | ||||
|  |   mutations: { | ||||
|  |     SET_ROUTERS: (state, routers) => { | ||||
|  |       state.addRouters = routers | ||||
|  |       state.routers = constantRouterMap.concat(routers) | ||||
|  |     }, | ||||
|  |     SET_SIDEBAR_ROUTERS: (state, routers) => { | ||||
|  |       state.sidebarRouters = constantRouterMap.concat(routers) | ||||
|  |     } | ||||
|  |   }, | ||||
|  |   //发送异步请求拿到数据
 | ||||
|  |   actions: { | ||||
|  |     GenerateRoutes({ | ||||
|  |       commit | ||||
|  |     }, asyncRouter) { | ||||
|  |       commit('SET_ROUTERS', asyncRouter) | ||||
|  |     }, | ||||
|  |     SetSidebarRouters({ | ||||
|  |       commit | ||||
|  |     }, sidebarRouter) { | ||||
|  |       commit('SET_SIDEBAR_ROUTERS', sidebarRouter) | ||||
|  |     } | ||||
|  |   } | ||||
|  | 
 | ||||
|  | } | ||||
|  | 
 | ||||
|  | //遍历后台传来的路由字符串,转换为组件对象
 | ||||
|  | export const filterAsyncRouter = (routers, isRewrite = false) => { | ||||
|  |   return routers.filter(router => { | ||||
|  |     if (isRewrite && router.children) { | ||||
|  |       router.children = filterChildren(router.children) | ||||
|  |     } | ||||
|  |     if (router.component) { | ||||
|  |       if (router.component === 'Layout') { // Layout组件特殊处理
 | ||||
|  |         router.component = Layout | ||||
|  |       } else if (router.component === 'ParentView') { | ||||
|  |         router.component = ParentView | ||||
|  |       } else { | ||||
|  |         const component = router.component | ||||
|  |         router.component = loadView(component) | ||||
|  |       } | ||||
|  |     } | ||||
|  |     if (router.children && router.children.length) { | ||||
|  |       router.children = filterAsyncRouter(router.children, router, isRewrite) | ||||
|  |     } | ||||
|  |     return true | ||||
|  |   }) | ||||
|  | } | ||||
|  | 
 | ||||
|  | function filterChildren(childrenMap) { | ||||
|  |   var children = [] | ||||
|  |   childrenMap.forEach((el, index) => { | ||||
|  |     if (el.children && el.children.length) { | ||||
|  |       if (el.component === 'ParentView') { | ||||
|  |         el.children.forEach(c => { | ||||
|  |           c.path = el.path + '/' + c.path | ||||
|  |           if (c.children && c.children.length) { | ||||
|  |             children = children.concat(filterChildren(c.children, c)) | ||||
|  |             return | ||||
|  |           } | ||||
|  |           children.push(c) | ||||
|  |         }) | ||||
|  |         return | ||||
|  |       } | ||||
|  |     } | ||||
|  |     children = children.concat(el) | ||||
|  |   }) | ||||
|  |   return children | ||||
|  | } | ||||
|  | 
 | ||||
|  | export const loadView = (view) => { | ||||
|  |   return (resolve) => require([`@/views/${view}`], resolve) | ||||
|  | } | ||||
|  | 
 | ||||
|  | export default permission | ||||
| @ -0,0 +1,240 @@ | |||||
|  | <template> | ||||
|  |  <div class="login" :style="'background-image:url('+ Background +');'"> | ||||
|  |     <el-form ref="loginForm" :model="loginForm" :rules="loginRules" label-position="left" label-width="0px" class="login-form"> | ||||
|  |       <h3 class="title"> | ||||
|  |         阅行集成后台管理 | ||||
|  |       </h3> | ||||
|  |       <el-form-item prop="username"> | ||||
|  |         <el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号"> | ||||
|  |           <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" /> | ||||
|  |         </el-input> | ||||
|  |       </el-form-item> | ||||
|  |       <el-form-item prop="password"> | ||||
|  |         <el-input v-model="loginForm.password" type="password" auto-complete="off" placeholder="密码" @keyup.enter.native="handleLogin"> | ||||
|  |           <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" /> | ||||
|  |         </el-input> | ||||
|  |       </el-form-item> | ||||
|  |       <el-form-item prop="code"> | ||||
|  |         <el-input v-model="loginForm.code" auto-complete="off" placeholder="验证码" style="width: 63%" @keyup.enter.native="handleLogin"> | ||||
|  |           <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" /> | ||||
|  |         </el-input> | ||||
|  |         <div class="login-code"> | ||||
|  |           <img :src="codeUrl" @click="getCode"> | ||||
|  |         </div> | ||||
|  |       </el-form-item> | ||||
|  |       <el-checkbox v-model="loginForm.rememberMe" style="margin:0 0 25px 0;"> | ||||
|  |         记住我 | ||||
|  |       </el-checkbox> | ||||
|  |       <el-form-item style="width:100%;"> | ||||
|  |         <el-button :loading="loading" size="medium" type="primary" style="width:100%;" @click.native.prevent="handleLogin"> | ||||
|  |           <span v-if="!loading">登 录</span> | ||||
|  |           <span v-else>登 录 中...</span> | ||||
|  |         </el-button> | ||||
|  |       </el-form-item> | ||||
|  |     </el-form> | ||||
|  |     <!--  底部  --> | ||||
|  |      <!-- <div v-if="$store.state.settings.showFooter" id="el-login-footer"> | ||||
|  |       <span v-html="$store.state.settings.footerTxt" /> | ||||
|  |       <span> ⋅ </span> | ||||
|  |       <a href="https://beian.miit.gov.cn/#/Integrated/index" target="_blank">{{ $store.state.settings.caseNumber }}</a> | ||||
|  |     </div> --> | ||||
|  |   </div> | ||||
|  | </template> | ||||
|  | 
 | ||||
|  | <script> | ||||
|  | import { encrypt } from "@/utils/rsaEncrypt"; | ||||
|  | import Config from "@/settings"; | ||||
|  | import Cookies from "js-cookie"; | ||||
|  | import Background from "@/assets/images/background.jpg"; | ||||
|  | import { getCodeImg } from '@/api/login' | ||||
|  | 
 | ||||
|  | export default { | ||||
|  |   //输出模块名称 | ||||
|  |   name: 'Login', | ||||
|  |   data() { | ||||
|  |     return { | ||||
|  |       //背景图 | ||||
|  |       Background: Background, | ||||
|  |       //登录验证码 | ||||
|  |       codeUrl: '', | ||||
|  |       //通行证 | ||||
|  |       cookiePass: '', | ||||
|  |       //默认登录信息--测试用 | ||||
|  |       loginForm: { | ||||
|  |         username: 'admin', | ||||
|  |         password: '123456', | ||||
|  |         rememberMe: false, | ||||
|  |         code: '', | ||||
|  |         uuid: '', | ||||
|  |       }, | ||||
|  |       //登录规则 | ||||
|  |       loginRules: { | ||||
|  |         username: [ | ||||
|  |           { required: true, trigger: 'blur', message: '用户名不能为空' }, | ||||
|  |         ], | ||||
|  |         password: [ | ||||
|  |           { required: true, trigger: 'blur', message: '密码不能为空' }, | ||||
|  |         ], | ||||
|  |         code: [ | ||||
|  |           { required: true, trigger: 'change', message: '验证码不能为空' }, | ||||
|  |         ], | ||||
|  |       }, | ||||
|  |       //加载状态是否显示 | ||||
|  |       loading: false, | ||||
|  |       //跳转定向 | ||||
|  |       redirect: undefined | ||||
|  |     }; | ||||
|  |   }, | ||||
|  |   watch: { | ||||
|  |     //监听路由变化 | ||||
|  |     $route: { | ||||
|  |       handler: function (route) { | ||||
|  |         this.redirect = route.query && route.query.redirect; | ||||
|  |       }, | ||||
|  |       //立即执行handler | ||||
|  |       immediate: true, | ||||
|  |     }, | ||||
|  |   }, | ||||
|  |   // 使用钩子初始化获取信息 | ||||
|  |   created() { | ||||
|  |     //获取验证码 | ||||
|  |     this.getCode(); | ||||
|  |     //获取用户名密码等 Cookie | ||||
|  |     this.getCookie(); | ||||
|  |     // token过期提示 | ||||
|  |     this.point(); | ||||
|  |   }, | ||||
|  |   methods: { | ||||
|  |     //获取验证码方法 | ||||
|  |     getCode() { | ||||
|  |       getCodeImg().then((res) => { | ||||
|  |         this.codeUrl = res.img; | ||||
|  |         this.loginForm.uuid = res.uuid; | ||||
|  |       }); | ||||
|  |     }, | ||||
|  |     //获取Cookie | ||||
|  |     getCookie() { | ||||
|  |       const username = Cookies.get('username'); | ||||
|  |       let password = Cookies.get('password'); | ||||
|  |       const rememberMe = Cookies.get('rememberMe'); | ||||
|  |       // 保存cookie里面的加密后的密码 | ||||
|  |       this.cookiePass = password === undefined ? '' : password; | ||||
|  |       password = password === undefined ? this.loginForm.password : password; | ||||
|  |       this.loginForm = { | ||||
|  |         username: username === undefined ? this.loginForm.username : username, | ||||
|  |         password: password, | ||||
|  |         rememberMe: rememberMe === undefined ? false : Boolean(rememberMe), | ||||
|  |         code: '', | ||||
|  |       }; | ||||
|  |     }, | ||||
|  |     handleLogin() { | ||||
|  |       this.$refs.loginForm.validate((valid) => { | ||||
|  |         // 获取登录信息 | ||||
|  |         const user = { | ||||
|  |           username: this.loginForm.username, | ||||
|  |           password: this.loginForm.password, | ||||
|  |           rememberMe: this.loginForm.rememberMe, | ||||
|  |           code: this.loginForm.code, | ||||
|  |           uuid: this.loginForm.uuid, | ||||
|  |         }; | ||||
|  |         //如果cookie通行证不匹配 | ||||
|  |         if (user.password !== this.cookiePass) { | ||||
|  |           //把密码进行加密处理 | ||||
|  |           user.password = encrypt(user.password); | ||||
|  |         } | ||||
|  |         if (valid) { | ||||
|  |           this.loading = true; | ||||
|  |           if (user.rememberMe) { | ||||
|  |             Cookies.set('username', user.username, { | ||||
|  |               expires: Config.passCookieExpires, | ||||
|  |             }); | ||||
|  |             Cookies.set('password', user.password, { | ||||
|  |               expires: Config.passCookieExpires, | ||||
|  |             }); | ||||
|  |             Cookies.set('rememberMe', user.rememberMe, { | ||||
|  |               expires: Config.passCookieExpires, | ||||
|  |             }); | ||||
|  |           } else { | ||||
|  |             Cookies.remove('username'); | ||||
|  |             Cookies.remove('password'); | ||||
|  |             Cookies.remove('rememberMe'); | ||||
|  |           } | ||||
|  |           this.$store | ||||
|  |             .dispatch('Login', user) | ||||
|  |             .then(() => { | ||||
|  |               this.loading = false; | ||||
|  |               this.$router.push({ path: this.redirect || '/' }); | ||||
|  |             }) | ||||
|  |             .catch(() => { | ||||
|  |               this.loading = false; | ||||
|  |               this.getCode(); | ||||
|  |             }); | ||||
|  |         } else { | ||||
|  |           console.log("提交错误!!"); | ||||
|  |           return false; | ||||
|  |         } | ||||
|  |       }); | ||||
|  |     }, | ||||
|  |     point() { | ||||
|  |       const point = Cookies.get('point') !== undefined; | ||||
|  |       if (point) { | ||||
|  |         this.$notify({ | ||||
|  |           title: "提示", | ||||
|  |           message: "当前登录状态已过期,请重新登录!", | ||||
|  |           type: "warning", | ||||
|  |           duration: 5000, | ||||
|  |         }); | ||||
|  |         Cookies.remove("point"); | ||||
|  |       } | ||||
|  |     }, | ||||
|  |   }, | ||||
|  | }; | ||||
|  | </script> | ||||
|  | 
 | ||||
|  | <style rel="stylesheet/scss" lang="scss"> | ||||
|  | .login { | ||||
|  |   display: flex; | ||||
|  |   justify-content: center; | ||||
|  |   align-items: center; | ||||
|  |   height: 100%; | ||||
|  |   background-size: cover; | ||||
|  | } | ||||
|  | .title { | ||||
|  |   margin: 0 auto 30px auto; | ||||
|  |   text-align: center; | ||||
|  |   color: #707070; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .login-form { | ||||
|  |   border-radius: 6px; | ||||
|  |   background: #ffffff; | ||||
|  |   width: 385px; | ||||
|  |   padding: 25px 25px 5px 25px; | ||||
|  |   .el-input { | ||||
|  |     height: 38px; | ||||
|  |     input { | ||||
|  |       height: 38px; | ||||
|  |     } | ||||
|  |   } | ||||
|  |   .input-icon { | ||||
|  |     height: 39px; | ||||
|  |     width: 14px; | ||||
|  |     margin-left: 2px; | ||||
|  |   } | ||||
|  | } | ||||
|  | .login-tip { | ||||
|  |   font-size: 13px; | ||||
|  |   text-align: center; | ||||
|  |   color: #bfbfbf; | ||||
|  | } | ||||
|  | .login-code { | ||||
|  |   width: 33%; | ||||
|  |   display: inline-block; | ||||
|  |   height: 38px; | ||||
|  |   float: right; | ||||
|  |   img { | ||||
|  |     cursor: pointer; | ||||
|  |     vertical-align: middle; | ||||
|  |   } | ||||
|  | } | ||||
|  | </style> | ||||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue