作者:花自飘零009玲玲 | 来源:互联网 | 2023-10-10 16:33
管理系统后端(java)请参考:https://blog.csdn.net/grd_java/article/details/121925792
本项目源码,码云:https://gitee.com/yin_zhipeng/vue-backstage-scaffolding.git
后台管理系统
,一般都是内部人员使用,所以对界面要求不高,一般都使用模板开发
。而前台系统
,是给游客使用,要凸显个性,所以一般自己开发,不使用模板
如果你想从头到尾写,可以参考我的前台系统,每个细节都会讲到(看完完全可以自己写个模板)
:@TODO 日后再写 这里是后台管理系统,我们使用模板"PanJiaChen的模板简洁版"
简洁版:https://github.com/PanJiaChen/vue-admin-template 加强版:https://github.com/PanJiaChen/vue-element-admin 如果你GitHub进不去
,可以到这里下载(码云)
:https://gitee.com/panjiachen/vue-admin-template.git 下载完成后,我们用它来当做项目,执行npm install --save 来下载相关依赖,然后通过npm run dev启动项目,最后浏览器查看项目
注意:::::::::
文章目录 注意::::::::: 一、概念和技术总结(重点,一定要搞懂) 1. vue 2. vue-admin-template模板文件解析 3. 异步相关,前后端交互 4. 导航守卫 二、单点登录实现 1. 后端接口和响应结果分析 2. 解决跨域,以及请求头.几乎所有项目都需要的配置,背下来吧。 3. 验证码展示 4. 单点登录,退出登录,根据后端API实现 1. api接口 2. 路由组件编写登录函数逻辑 3. 修改store(vuex)异步逻辑 三、后台管理系统实现
一、概念和技术总结(重点,一定要搞懂) 这里总结项目中用到的前端知识,后面将不再赘述
大家最起码需要混个眼熟,后面代码中用到,不至于不知道这是干什么的(现在好多人,会用,但不知道为什么这么用,那你怎么优化和调优,调错呢?
) 如果这里有你不会或没见过的东西(看了我的介绍不懂的),可以参考官方文档(说明你压根没学过Vue的相关知识,直接百度Vue官网就行) 1. vue props :适用于父子组件通信的场景,有一个容易混淆的点,如下: 如果父组件利用props给子组件传递数据时,传递的是一个函数,其实就是子组件给父组件传递数据(因为调用的是父组件的函数)。 如果传递的不是函数,那么才是真正的父组件给子组件传递了数据(子组件使用传来的数据). 可以指定父组件传输的类型,{type:Array},也可以指定默认值{type:Array,default:[]},也可以什么都不指定,[‘todos’] 自定义事件 :适用于子组件给父组件传递数据, $ on、和$ emit全局事件总线$bus :适用于任何场景,Vue.prototype. $bus = this;pubsub-js发布和订阅 :适用于任何场景,但是Vue用的不多,一般React框架经常使用Vuex :适用于任何场景,用的非常多solt插槽 :使用于针对结构(标签)的父子组件通信,常用的有默认插槽,具名插槽和作用域插槽 2. vue-admin-template模板文件解析 文件目录解析(注意:以下所有文件夹和文件,你自己写效果也一样,并不是必须在这个模板文件中才能用)
build mock node_modules p ublic src App. vue main. js permission. js settings. editorconfig. env. development. env. production. env. staging. eslintignore. eslintrc. js. gitignore. travis. yml babel. config. js jest. config. js LICENSE jsconfig. json package. json postcss. config. js vue. config. js
首先,将路由模块挂载到Vue,然后将所有路由配置封装到常量constantRoutes中,然后回调函数创建路由,挂载了常量constantRoutes,并将函数放置到常量createRouter,随后,将createRouter()这个函数常量,换了个简单的名字router。最后对外暴露router和一个重置路由的函数resetRouter() 这样做,我们可以直接通过$router操作和获取路由相关信息 jsconfig.json文件配置src别名为@解析
3个环境配置文件,可以通过webpack对外暴露的函数process获取,注意配置文件中内容,要以VUE_APP_*****开头(就和,java类名首字母要大写一样,大家要共同遵守)
我们看下开发环境的配置文件的配置内容,测试是否能正确获取 main.js文件中输出process和process.env,查看结果 console. log ( process) console. log ( process. env)
这里封装了对于权限的功能函数 index.js文件,主要是掌控Vuex的大局,挂载到Vue getters.js文件,封装getters操作,这里统一使用lambda表达式(箭头函数),使用了上面配置的modules中的app和user中内容,例如state.app.***** a => return a;
user.js,主要提供登录的state,setter(action和mutations),并暴露他们.另外app.js、settings.js文件和user.js差不多 3. 异步相关,前后端交互 1. 当年PanJiaChen开发此模板时,还没有async函数(ES6的语法),所以使用传统Promise处理异步,我们后面统一将其改造为使用async函数,对于Promise和async请参考文章:https://blog.csdn.net/grd_java/article/details/105384601
我们发现上面request.js中,请求路径的封装,使用的就是配置文件中的VUE_APP_BASE_API,我们这里配置什么,request.js发起的请求就会请求什么,所以我们这里可以配置上我们的后端接口,或者网关地址 注意,配置的地址,一定要指定协议,例如http://,否则会无法正常请求转发 4. 导航守卫 不知道的参考官方文档https://router.vuejs.org/zh/guide/advanced/navigation-guards.html
此文件主要控制路由跳转的业务,像一个导航一样,可以理解为路由的拦截器 此文件主要完成的功能是,拦截一个路由跳转,判断用户是否有token,如果有,判断是否跳转路由为/login(登录路径),如果是,不允许跳转,从定向到"/"首页。如果不是登录路径,尝试获取用户信息,获取不到,尝试重新获取,重新获取失败,删除token,让用户进入登录页面重新登录 二、单点登录实现 登录页面直接使用模板提供的即可,我们对其样式进行一些修改,以让你知道如何对其自定义
更换背景图片,也可以使用@
符号,只是需要加一个~
前缀 assets文件加放一张back.jpg图片 修改css样式 1. 后端接口和响应结果分析 验证码:请求captcha这个url返回一张图片 登录,Post请求,传输username,password,code3个参数,全部正确,登录成功,返回tokenHead和token,最终token规定格式为,tokenHead + “空格” + token,也就是Bearer eyJh…、成功状态码20000,失败状态码20001 当前登录用户信息,需要携带token,注意,token格式,以及header的name为authorization
2. 解决跨域,以及请求头.几乎所有项目都需要的配置,背下来吧。 1. 首先,我们知道环境配置文件中,有VUE_APP_BASE_API这个东西,我们通过这个来规定请求路径,我们可以规定它.改完记得重启项目(我们是开发环境,所以修改.env.development文件)
2. 然后我们通过修改webpack的配置文件vue.config.js,配置跨域代理,主要位置,别写错位置,同样,配置完记得重启项目
proxy: { [ process. env. VUE_APP_BASE_API] : { target: `http: / / localhost: 8001 `, pathRewrite: { [ '^' + process. env. VUE_APP_BASE_API] : '' } } } ,
3. token请求头这种东西,直接配置到请求拦截器中就好了,request.js,注意token请求头的key必须为authorization
service. interceptors. request. use ( config = > { if ( store. getters. token) { config. headers[ 'authorization' ] = getToken ( ) } return config} , error = > { console. log ( error) return Promise . reject ( error) } )
3. 验证码展示 后端直接返回一张图片给我们,我们可以通过window.URL.createObjectURL(response)来获取图片的一个url地址 window.URL.createObjectURL用于创建一个新的对象URL,该对象URL可以代表某一个指定的File对象或Blob对象
响应类型必须是blob或file两种格式(responseType:‘blob’ 或者 responseType:‘file’)
1. 首先,我们后端的验证码功能没有响应码,而我们使用的模板,在request.js中封装了请求拦截器和响应拦截器,致命的是,响应拦截器直接拦截所有响应码不是20000的响应
这样做的好处是,所有请求如果出错(响应码不是20000),统一进行错误逻辑,但这也同样是缺点。因为针对不同错误,我们希望有不同的反馈,而不是统一的一种 所以我们要丰富其功能(一个if就搞定),对于不需要code状态码的响应,如果有响应体,表示响应成功,否则表示响应失败 2. 封装api请求,注意一定要将响应类型设置为’blob’(responseType:‘blob’)
api/user.js添加验证码接口 export function captcha ( ) { return request ( { url: 'captcha' , method: 'get' , responseType: 'blob' } ) }
3. login页面,login/index.js文件引入api,然后展示验证码
编写函数getImgCode,通过window.URL.createObjectURL(response)封装图片为url async getImgCode ( ) { await captcha ( ) . then ( response => { this . codesrc = window. URL . createObjectURL ( response) } ) } ,
添加组件和样式&#xff0c;指定函数回调(单击事件)&#xff0c;以实现单击图片&#xff0c;重新生成验证码 < el- form- item prop&#61; "code" class &#61; "code" > < span class &#61; "svg-container" > < ! -- < svg- icon icon- class &#61; "el-icon-s-flag" / > -- > < i class &#61; "el-icon-edit" > < / i> < / span> < el- inputclass &#61; "code-input" ref&#61; "code" type&#61; "text" v- model&#61; "loginForm.code" placeholder&#61; "验证码" name&#61; "code" tabindex&#61; "2" auto- complete&#61; "on" &#64;keyup. enter. native&#61; "handleLogin" / > < / el- form- item> < img : src&#61; "codesrc" class &#61; "code-img" &#64;click&#61; "getImgCode" > . code{ width: 70 % ; float: left; } . code- img{ float: right; width: 29.6 % ; }
4. 单点登录&#xff0c;退出登录&#xff0c;根据后端API实现 登录后&#xff0c;查看token 退出登录&#xff0c;查看token 1. api接口 api文件夹user.js文件&#xff0c;修改login&#xff0c;getInfo和logout三个接口
2. 路由组件编写登录函数逻辑 我们发现&#xff0c;此模板所有登录逻辑都在view/login/index.vue文件中的handleLogin方法中&#xff0c;对其进行修改
handleLogin ( ) { this . $refs. loginForm. validate ( valid &#61; > { if ( valid) { this . loading &#61; true this . $store. dispatch ( &#39;user/login&#39; , this . loginForm) . then ( ( ) &#61; > { this . $router. push ( { path: this . redirect || &#39;/&#39; } ) this . loading &#61; false } ) . catch ( ( ) &#61; > { this . loading &#61; false this . getImgCode ( ) } ) } else { console. log ( &#39;error submit!!&#39; ) this . getImgCode ( ) return false } } ) }
3. 修改store&#xff08;vuex&#xff09;异步逻辑 所有操作都在store/user.js中,我们需要修改login和getInfo以及logout
async login ( { commit } , userInfo) { const { username, password, code} &#61; userInfo; let result &#61; await login ( { username: username. trim ( ) , password: password, code: code} ) ; if ( result. code&#61;&#61; 20000 ) { const token &#61; result. data. tokenHead&#43; &#39; &#39; &#43; result. data. token; commit ( "SET_TOKEN" , token) ; setToken ( token) } else { return Promise . reject ( new Error ( result. message) ) ; } } , async getInfo ( { commit, state } ) { let result &#61; await getInfo ( state. token) ; if ( result. code &#61;&#61; &#61; 20000 ) { const { loginInfo } &#61; result. dataif ( ! loginInfo) { return reject ( &#39;验证失败&#xff0c;请重新登录.&#39; ) ; } const { username} &#61; loginInfo; commit ( &#39;SET_NAME&#39; , username) ; commit ( &#39;SET_AVATAR&#39; , &#39;https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif&#39; ) } else { return Promise . reject ( new Error ( result. message) ) ; } } , async logout ( { commit, state } ) { let result &#61; await logout ( state. token) ; if ( result. code &#61;&#61; &#61; 20000 ) { removeToken ( ) resetRouter ( ) commit ( &#39;RESET_STATE&#39; ) } else { return Promise . reject ( new Error ( result. message) ) ; } } ,
三、后台管理系统实现 由于篇幅原因&#xff0c;我将其放在另一篇文章中&#xff1a;&#64;TODO 还没写完