{{ entry.content }}
项目背景:受疫情的影响,许多企业由线上办公转为线下办公。随着线上办公的人数的增多,线上办公的优点逐步凸显:通过实现工作流程的自动化、节省企业办公费用、实现绿色办公,同时提升办公效率。
项目介绍:本项目实现了一个在线办公系统,用来管理日常办公事物的:日常流程审批,新闻,通知,公告,文件信息,财务,人事,费用,资产,行政,项目,移动办公等。通过软件的方式让办公系统根据方便管理,提高整体的管理运营水平。
实现方式:本项目基于Vue+Spring Boot构架一个前后端分离项目。前端使用社区非常活跃的开源框架vue进行构建。简单地说,前后端分离 的核心思想是前端页面通过 ajax 调用后端的 restuful api 进行数据交互,而 单页面应用(single page web application,SPA),就是只有一张页面,并在用户与应用程序交互时动态更新该页面的 Web 应用程序。
本项目采用前后端分离开发模式,使用Spring Boot构建后端。
前端使用的技术有:
Vue、Vue-cli、Vuex、VueRouter、ElementUI、Axios、ES6、Webpack、WebSocket、font-awesome、js-file-download、vue-chat
项目搭建:Vue-cli ;状态管理:Vuex ;路由管理:VueRouter;UI界面:ElementUI;通讯框架:Axios ;
前端语法:ES6;打包工具:Webpack;在线聊天:WebSocket;字体:font-awesome;文件上传下载:js-file-download;在线聊天开源项目:vue-chat
前端模块分为:登录、职位管理、职称管理、部门管理、操作员历、员工管理、工资账套管理、个人中心、在线聊天
前后端之间通过 RESTful API 传递 JSON 数据进行交流。不同于 JSP 之类,后端是不涉及页面本身的内容的。在开发的时候,前端用前端的服务器(Nginx),后端用后端的服务器(Tomcat),当我开发前端内容的时候,可以把前端的请求通过前端服务器转发给后端(称为反向代理),这样就能实时观察结果,并且不需要知道后端怎么实现,而只需要知道接口提供的功能。
目录
一、项目简介
1.1 技术架构
1.2 前端技术架构
1.3 云E办(前端)
二、Vue.js框架
2.1Vue特性
2.2 MVVM设计模式
2.3 vue相关组件
三、搭建vue.js项目
3.1 搭建vue.js项目
3.2 构建前端项目
3.3 vue项目结构分析
3.4 安装 Element-UI
3.5 安装axios
3.6 安装Vuex
3.7 安装VueRouter
3.8 安装font-awesome
四、前端拦截器
4.1 配置登陆拦截器
4.2 axios请求拦截器request
4.3 axios响应拦截器response
4.4 封装请求
4.5 代码实现src/utils/api.js
4.6 main.js全局引入封装请求
五、登陆页面
5.1 样式设计
5.2 登陆页功能设计
5.3 Login.vue登录页
5.4 配置页面路由——router/index.js
5.5 前端路由导航守卫
main.js
5.6 解决前后端跨域
前端反向代理
5.7 运行项目
六、首页页面
6.1 菜单功能设计与实现
配置store/index.js
在Main.js中引入store
6.2 封装菜单请求工具
后端请求菜单接口返回信息
更新main.js
6.3 样式设计
6.4 Home.vue代码
6.5 更新路由router/index.js
6.6 index.html消除边距
七、基础信息设置
7.1 样式设计
Tabs 标签页
7.2 组件化开发
7.3 SysBasic.vue
7.4 部门管理DepMana.vue组件
7.5 职位管理PosMana.vue组件
PosMana.vue
7.6 职称管理JobLevelMana.vue组件
7.7 权限组PositionMana.vue组件
八、操作员管理
SysAdmin.vue
九、员工资料
EmpBasic.vue
十、工资账套管理
SalSob.vue
十一、员工账套设置
SalSobCfg.vue
十二、聊天功能
整合项目
components
card.vue
list.vue
message.vue
usertext.vue
十三、个人中心
AdminInfo.vue
十四、源代码
Web前端开发从开始到兴起再到如今,已经发展了很多年,同时累积了非常多的开发经验和开发工具。过去的开发者们的一些经验也都经过了技术发展,环境变化等重重考验,他们所创造出来的思想、技术和工具,也非常值得我们后来开发者的借鉴和学习,甚至直接拿来使用。因为开发工具和开发语言不管怎么发展,不管差异有多大,但是他们所解决的问题都是相似而统一的,可以归纳为:
(1)扩充JavaScript、html和CSS三种编程语言本身的语言能力;
(2)解决开发过程中重复的工作;
(3)将项目进行模块化;
(4)解决功能复用和变更问题;
(5)解决开发和产品环境差异问题;
(6)解决发布流程问题。
为了解决上述问题便产生了工程化的思想,工程化就是这种避免重复造轮子的最好实践。Vue.js是一套构建用户界面的渐进式框架,它是由中国程序开发者尤雨溪在2013年开发。因为Vue.js简洁的语法设计、轻量快速的特点在技术社区中深受开发者欢迎,因而也促进了Vue.js的推广和流行。Vue.js在相关的工具和支持库配合使用下,也能完美地驱动复杂的单页应用,开发一个大型的Web应用。Vue.js在权威的JavaScript趋势榜上已经蹿升到了总榜的前30位且能持续的排在榜单的前列,显然已成为一个全球顶尖的JavaScript框架。Vue.js的生态不仅体现在趋势榜上,其配套的数据管理库vuex、路由管理库Vue-router、打包工具、开发者调试插件和项目脚手架等工具和库也都逐渐开发成型,同样也拥有非常活跃的技术社区。
Vue.js是一个轻量级的MVVM前端框架,可以用于构建渐进式用户界面。开发者在Vue.js中构建前端页面时,只用关心页面逻辑的实现。Vue.js最大的特点是由底层逐层向上应用,不仅易上手还能兼容大量的第三方库。
虚拟DOM
vue区别于传统框架的特点一是虚拟DOM。浏览器进行DOM操作会带来较大的开销,因此在Vue中通过diff算法构建了Virtual DOM,数据每次更新时比对最小变化,重新构建Virtual DOM。
响应式
Vue.js的核心被设计为一个响应的数据绑定系统,因此可以非常方便的将数据与DOM保持同步。在使用jQuery手工操作DOM时往往容易编写命令式的、重复的并且易错的代码。而Vue.js拥抱数据驱动的视图概念意味着在普通HTML模板中使用特殊的语法将DOM“绑定”到底层数据。这种绑定一旦创建,DOM便与数据实现了保持同步。每当对数据进行了修改则会相应的更新DOM。通过这种方式,在开发应用中,所有的业务逻辑就几乎只用直接修改数据,而不必与对DOM进行单独的更新操作,使得数据和DOM更新不会搅合在一起。这也让应用的代码更容易撰写、理解与维护。
组件化
在大型的应用开发中,往往会将应用抽象为多个相对独立的模块,目的是为了代码块的可复用性和维护性。然而只有当考虑复用性的时候才会将某一模块做成单独的一个组件,实际上,Web的视图界面也完全可以分为一个组件树。组件化是Vue.js最强大的功能之一。组件可以将视图页面的标签元素进行扩展然后进行封装,最终变成可重复使用的代码。从高层面上理解,组件也可以是一个自定义的元素,然后通过Vue.js的编译器的编译,可以为这个元素添加某种特殊的功能。同时,组件也可以是原生的HTML元素,通过is特性扩展。Vue.js和同样强调组件化思想的前端框架React.js有些类似,但是要比其更加轻量,简洁和先进。
组件化通常是指Vue.js能够将JavaScript代码、超文本标记语言(hypertext markup language, HTML)代码和层叠样式表 (cascadingstyle sheets, CSS)代码写在同一个文件里。开发者在实际开发中常常会遇到页面的功能需要多次使用的情况,这时可以在components目录下,构建可复用的组件。如果其他页面需要使用该组件,那么可以通过import方法进行引入。由于页面由多个组件构成,组件与组件之间耦合度较低,可大量减少重复性代码。
局部刷新
vue是一个单页面应用,单页面应用的主要特性就是网页的局部刷新,网页应用通过控制控制路由调用AJAX,后台只需要提供接口即可实现。这样的应用优势明显,首先在用户体验上会更人性化,不需要刷新整个页面,因此加载速度快速,体验更好。
基于B/S架构的Java Web应用系统在被开发时,前端页面的绘制与美化是系统开发的重要工作。页面的绘制与交互一般是基于对文档对象模型(document object model, DOM)元素节点和数据的操控来完成的,但直接操作DOM节点极易产生错误。近年来,随着前端技术的发展,涌现了各种各样的前端框架,这些框架基于MVVM (Model-View-ViewModel)设计模式,为前端工程的开发与维护带来了许多便利 。MVVM设计模式基于传统的MVC设计模式衍生而来,全称为Model-View-ViewModel。Model层负责持有用户数据,View层负责在屏幕上显示视觉元素和控件,ViewModel层负责将模型转换为可在视图上直接显示的值。
脚手架vue-cli
快速开发工具vue-cli。它可以帮助开发者基于vue.js框架进行快速开发。vue-cli将各种工具标准化,确保各种构建工具能够基于智能的默认配置平稳衔接,使开发者在撰写前端应用时更加专注,不必花费很长时间去调整项目配置。
路由Vue-router
Vue.js构建的单页面的Web应用需要基于路由和组件。其中,路由的主要作用是用来设定访问路径,并将访问路径和视图组件相映射起来。在单页面的Web应用里,路径之间的跳转和切换其实是对应组件之间的切换。和React.js一样,Vue.js自身是也是不具有路由功能的。因此,在Vue.js框架使用的时候需要与一个路由工具库相互协作,即Vue-router。Vue-router能够将不同层级并且嵌套的路由关系映射到相应的嵌套的组件,并且提供了一个细致的控制路径跳转的解决方式。
状态管理vuex
Vue.js的视图变化都基于组件的状态,所以当构建大型的Web应用的时候会产生大量的组件状态,从而需要对这些状态进行管理。由于vue的“单向数据流”无法解决多个组件共享状态的问题,所以才有了vuex。Vuex便是一个集中式存储和管理应用的所有组件的状态的管理架构,专门为配合使用了Vue.js框架的应用而设计。它借鉴了React.js的状态管理工具Flux和Redux的设计理念,并对一些概念进行了简化,从而能更好的发挥Vue.js的数据响应机制。
通信框架axios
通信框架。因为vue的边界很明确,就是为了处理DOM,所以不具备通信能力,此时就需要额外使用一个通信框架与服务器交互;当然也可以直接使用jQuery提供的AJAX通信功能。经典的Ajax技术实现了网页的局部数据刷新,而Axios又对Ajax进行再次封装,它具备如下特征:
(1)从浏览器中创建XMLHttpRequest
(2)从node.js中发出http请求
(3)支持PromiseApi
(4)拦截请求和响应
(5)转换请求和相应数据
(6)取消请求
(7)自动转换JSON数据
(8)客户端支持防止CSRF/XSRF
Axios插件很好的封装了Ajax技术,在项目开发中写法简洁明了,因此不容易出错,即使出错也易于排查。
打包工具webpack
前端开发和其他开发工作的主要区别,首先是前端基于多语言、多层次的编码和组织工作,其次前端产品的交付是基于浏览器的,这些资源是通过增量加载的方式运行到浏览器端,如何在开发环境组织好这些碎片化的代码和中资源,并且保证他们在浏览器快速、优雅的加载和更新,就需要一个模块化系统。
webpack是一个大型js应用程序的模块化工具,会自动处理命名空间等一系列js编程遇到的问题。当webpack处理js的应用程序时,它会构建一个复杂的依赖关系图,这个关系图中包含了应用程序依赖的模块,甚至包含了很多静态资源,然后webpack会将这些模块打包成一个或多个大的模块,在应用程序中引用。
ES6模块
vue通常用es6来写,用export default导出,其下面可以包含数据data,生命周期(mounted等),方法(methods)等,具体语法请看vue.js文档。ES6标准增加了javascript语言层面的模块体系定义。ES6模块的设计思想,是尽量静态化,使编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS和AMD模块,都只能在运行时确定这些东西。
UI框架
ElementUI,饿了么出
环境准备
安装Node.js(>=6.x,首选8.x)本项目是v14.18.0版本
安装 Vue CLI
因为需要使用 npm 安装 Vue CLI,而 npm 是集成在 Node.js 中的,所以第一步我们需要安装 Node.js,访问官网 Node.js,首页即可下载。
下载完成后运行安装包,一路下一步就行。
然后在 cmd 中输入 node -v,检查node是否安装成功。
输入 npm -v 查看npm版本号
输入 npm -g install npm ,将 npm 更新至最新版本。
之后,使用 npm install -g vue-cli 安装脚手架。(本项目使用版本2.9.6)
注意此种方式安装的是 2.x 版本的 Vue CLI,最新版本需要通过 npm install -g @vue/cli 安装。新版本可以使用图形化界面初始化项目,并加入了项目健康监控的内容,但使用新版本创建的项目依赖与这个教程不太相符,折腾起来比较麻烦。
安装Node.js的淘宝镜像加速器cnpm
大部分情况使用npm,遇到安装不了的使用cnpm
npm install cnpm -g
或npm install --registry=https://registry.npm.taobao.org
通用方法
直接使用命令行构建项目。
然后执行命令 vue init webpack yeb,这里 webpack 是以 webpack 为模板指生成项目,还可以替换为 pwa、simple 等参数,这里不再赘述。
在程序执行的过程中会有一些提示,可以按照默认的设定一路回车下去,也可以按需修改,比如下图问我项目名称是不是 wj-vue,直接回车确认就行。
这里还会问是否安装 vue-router,一定要选是,也就是回车或按 Y,vue-router 是我们构建单页面应用的关键。
还有是否使用 es-lint,选N。
接下来等待项目构建完成就 OK 了。
可以看到 workspace 目录下生成了项目文件夹 需要在该文件夹执行 npm install ,npm run build 再执行 npm run dev
访问 http://localhost:8080,查看网页 demo,大工告成!
注:在vue项目中,有的时候需要执行npm run serve启动项目,有的时候需要用npm run dev,具体有什么不一样呢?
区别
dev默认是[email protected]默认支持的命令;
serve默认是[email protected]及以上版本默认支持的命令。
├── build --------------------------------- 项目构建(webpack)相关配置文件,配置参数什么的,一般不用动
│ ├── build.js --------------------------webpack打包配置文件
│ ├── check-versions.js ------------------------------ 检查npm,nodejs版本
│ ├── dev-client.js ---------------------------------- 设置环境
│ ├── dev-server.js ---------------------------------- 创建express服务器,配置中间件,启动可热重载的服务器,用于开发项目
│ ├── utils.js --------------------------------------- 配置资源路径,配置css加载器
│ ├── vue-loader.conf.js ----------------------------- 配置css加载器等
│ ├── webpack.base.conf.js --------------------------- webpack基本配置
│ ├── webpack.dev.conf.js ---------------------------- 用于开发的webpack设置
│ ├── webpack.prod.conf.js --------------------------- 用于打包的webpack设置
├── config ---------------------------------- 配置目录,包括端口号等。我们初学可以使用默认的。
│ ├── dev.env.js -------------------------- 开发环境变量
│ ├── index.js ---------------------------- 项目配置文件
│ ├── prod.env.js ------------------------- 生产环境变量
│ ├── test.env.js ------------------------- 测试环境变量
├── node_modules ---------------------------- npm 加载的项目依赖模块
├── src ------------------------------------- 我们要开发的目录,基本上要做的事情都在这个目录里。
│ ├── assets ------------------------------ 静态文件,放置一些图片,如logo等
│ ├── components -------------------------- 组件目录,存放组件文件,可以不用。
│ ├── main.js ----------------------------- 主js
│ ├── App.vue ----------------------------- 项目入口组件,我们也可以直接将组件写这里,而不使用 components 目录。
│ ├── router ------------------------------ 路由
├── static ---------------------------- 静态资源目录,如图片、字体等。
├── .babelrc--------------------------------- babel配置文件
├── .editorconfig---------------------------- 编辑器配置
├── .gitignore------------------------------- 配置git可忽略的文件
├── index.html ------------------------------ 首页入口文件,你可以添加一些 meta 信息或统计代码啥的。
├── package.json ---------------------------- node配置文件,记载着一些命令和依赖还有简要的项目描述信息
├── .README.md------------------------------- 项目的说明文档,markdown 格式。想怎么写怎么写,不会写就参照github上star多的项目,看人家怎么写的
主要文件详解
src——[项目核心文件]
在vue-cli的项目中,其中src文件夹是必须要掌握的,因为基本上要做的事情都在这个目录里。
index.html——[主页]
index.html如其他html一样,但一般只定义一个空的根节点,在main.js里面定义的实例将挂载在根节点下,内容都通过vue组件来填充,构建的文件将会被自动注入,也就是说我们编写的其它的内容都将在这个 div 中展示。整个项目只有这一个 html 文件,所以这是一个 单页面应用,当我们打开这个应用,表面上可以有很多页面,实际上它们都只不过在一个 div 中。
vuedemo
App.vue——[根组件]
这个文件称为“根组件”,因为其它的组件又都包含在这个组件中。.vue 文件是一种自定义文件类型,在结构上类似 html,一个 .vue 文件即是一个 vue 组件。
一个vue页面通常由三部分组成:模板(template)、js(script)、样式(style)
【template】
其中模板只能包含一个父节点,也就是说顶层的div只能有一个(例如上面代码,父节点为#app的div,其没有兄弟节点)。这里也有一句
【script】
SessionStorage.setItem()中,为了使axios做下一次请求时获取token认证,登录之后拿到token放到sessionStrorage里
// 存储用户 token 到 sessionStorage
const tokenStr = resp.obj.tokenHead + resp.obj.token;
window.sessionStorage.setItem('tokenStr', tokenStr);
import Vue from 'vue'
import Router from 'vue-router'
import Login from "@/views/Login";
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Login',
component: Login,
hidden: true // 不会被循环遍历出来
},
]
})
登录页面的开发似乎已经较为完善了,但其实还没有完,因为这个登录页面其实没有用,别人直接输入首页的网址,就可以绕过登录页面。为了让它发挥作用,我们还需要开发一个拦截器。使用钩子函数判断是否拦截函数及在某些时机会被调用的函数。这里我们使用 router.beforeEach(),意思是在访问每一个路由前调用。to 要去的路由; from 来自哪里的路由 ; next() 放行。
通过sessionStorage.getItem('user')获取用户的token,如果token不存在则需要登陆。
在判断是否为if (to.path == '/')登陆页,是的话放行,否则按用户指定的路由登陆;
// 使用 router.beforeEach 注册一个全局前置守卫
router.beforeEach((to, from, next) => {
// to 要去的路由; from 来自哪里的路由 ; next() 放行
// 用户登录成功时,把 token 存入 sessionStorage,如果携带 token,初始化菜单,放行
if (window.sessionStorage.getItem('tokenStr')) {
// 如果用户不存在
//待首页功能部分完善后补充
} else {
if (to.path === '/') {
next()
} else {
next('/?redirect=' + to.path)
}
}
})
前端端口默认8080,假设后端端口是8081,那8080如何访问到8081的数据,我们通过Node.js实现端口自动转发。浏览器的同源策略:两个页面必须具有相同的协议(protocol)主机(host)端口号(port)。同源策略是浏览器的一种安全机制,它是指浏览器会阻止对非同源页面的DOM操作以及XMLHttpRequest对象向非同源服务器发起http请求。请求一个接口时,出现Access-Control-Allow-Origin等,说明出现请求跨域了。vue中解决跨域的方法:配置vue.config.js文件,如果没有就自行新建一个。
原理:
1.将域名发送给本地的服务器(localhost:8080)
2.再由本地的服务器去请求真正的服务器
3.因为请求是从服务端发出的,所以不存在跨域的问题了。
在vue中是由node.js自动进行的
vue.config.js
修改proxyTable 请求地址经过node.js后代理到后端地址8081
proxyTable: {
'/': {
changeOrigin: true, //跨域
target: 'http://localhost:8081',
pathRewrite: {
// '^/api': ''
}
},
},
我们的项目虽然本质上是单页面应用,但表面上有多个功能页面。为了方便用户在这各个页面之间切换,我们需要添加一个导航栏。这个导航栏的要求很简单:
能够在每个页面显示
美观
为了实现第一个要求,我们需要把导航栏放在其它页面的父页面中(对 Vue 来说就是父组件),之前我们讲过,App.vue 是所有组件的父组件,但把导航栏放进去不合适,因为我们的登录页面中不应该显示导航栏。为了解决这个问题,我们在views目录下直接新建一个组件,命名为 Home.vue。和 App.vue 一样,写入了一个
Home.vue整体上实现了首页左侧菜单的获取和展示,右上角的个人中心的设置。从store.state中获取当前菜单信息、当前用户的登陆信息.。
需要文件目录如下:views/emp基本资料 新建 EmpBasic.vue EmpAdv.vue
views/per 员工资料新建 PerEmp.vu PerEc.vue PerTrain.vue PerSalary.vue PerMv.vue
views/sal 工资账套 SalSob.vue SalSobcfg.vue SalTable.vue SalMonth.vue SalSearch.vue
views/sta 综合信息统计 新增StaAll.vue StaScore.vue StaPers.vue StaRecord.vue
views/sys 系统管理 新增 SysBasic.vue SysConfig.vue SysLog.vue SysAdmin.vue SysData.vue SysInit.vue
通过vuex进行路由状态管理
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// 导入 Vuex
const store = new Vuex.Store({
state: {
routes: []
},
mutations: { // 与 state 同步执行;可以改变 state 对应的值的方法
// 初始化路由 菜单
initRoutes(state, data) {
state.routes = data
},
},
// 异步执行
actions: {
}
})
export default store;
import store from './store'
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
我们设计的菜单是根据用户信息加载的路由信息,即不同用户可能有不同的菜单权限。接口返回的菜单信息如下。通过children表示子菜单,子菜单中的parentId与父菜单的id相等时表示一个确定的父子菜单关系。如下的关系表示有一个层级菜单“员工资料/基本资料”。
如果store.state.routes有数据,初始化路由菜单。通过getRequest('/system/config/menu')方法从后端获取路由数据,按照层次关系拆分。
如何根据接口中的component字段找到对应的代码路径呢?
通过对接口对象中的component字段分类查找,例如component以Home开头,源代码在src/views/Home.vue中。
if (component.startsWith('Home')) {
require(['@/views/' + component + '.vue'], resolve);
}
initMenu方法将路由数据存于store中,如果store中有数据则无需初始化,否则,初始化。
什么时候调用?每一个页面都需要调用初始化菜单方法。放在路由拦截器里,每次访问路由都要执行一次。
import {getRequest} from "@/utils/api";
// 菜单请求工具类
// router 路由; store Vuex
export const initMenu = (router, store) => {
// 如果有数据,初始化路由菜单
if (store.state.routes.length > 0) {
return;
}
getRequest('/system/config/menu').then(data => {
// 如果数据存在 格式化路由
if (data) {
// 格式化好路由
let fmtRoutes = formatRoutes(data)
// 添加到 router
router.addRoutes(fmtRoutes)
// 将数据存入 Vuex
store.commit('initRoutes',fmtRoutes)
// 连接 WebSocket
store.dispatch('connect')
}
})
}
export const formatRoutes = (routes) => {
let fmtRoutes = []
routes.forEach(router => {
let {
path,
component,
name,
iconCls,
children
} = router;
// 如果有 children 并且类型是数组
if (children && children instanceof Array) {
// 递归
children = formatRoutes(children)
}
// 单独对某一个路由格式化 component
let fmRouter = {
path: path,
name: name,
iconCls: iconCls,
children: children,
component(resolve) {
// 判断组件以什么开头,到对应的目录去找
if (component.startsWith('Home')) {
require(['@/views/' + component + '.vue'], resolve);
}else if (component.startsWith('Emp')) {
require(['@/views/emp/' + component + '.vue'], resolve);
}else if (component.startsWith('Per')) {
require(['@/views/per/' + component + '.vue'], resolve);
}else if (component.startsWith('Sal')) {
require(['@/views/sal/' + component + '.vue'], resolve);
}else if (component.startsWith('Sta')) {
require(['@/views/sta/' + component + '.vue'], resolve);
}else if (component.startsWith('Sys')) {
require(['@/views/sys/' + component + '.vue'], resolve);
}
}
}
fmtRoutes.push(fmRouter)
})
return fmtRoutes
}
获取当前用户登陆信息
将当前用户信息保存在sessionStorage的user中,每次路由切换时获取用户的登陆信息。
// 使用 router.beforeEach 注册一个全局前置守卫
router.beforeEach((to, from, next) => {
// to 要去的路由; from 来自哪里的路由 ; next() 放行
// 用户登录成功时,把 token 存入 sessionStorage,如果携带 token,初始化菜单,放行
if (window.sessionStorage.getItem('tokenStr')) {
initMenu(router, store)
// 如果用户不存在
if (!window.sessionStorage.getItem('user')
) {
// 判断用户信息是否存在
return getRequest('/admin/info').then(resp => {
if (resp) {
// 存入用户信息,转字符串,存入 sessionStorage
window.sessionStorage.setItem('user', JSON.stringify(resp))
// 同步用户信息 编辑用户
store.commit('INIT_ADMIN',resp)
next();
}
})
}
next();
} else {
if (to.path === '/') {
next()
} else {
next('/?redirect=' + to.path)
}
}
})
登陆后的前端页面被分解为上方导航栏,左侧菜单栏和中间的主要功能区域,对于不同页面的切换,仅需要变化中间功能区域内容,提高了代码重用性。首先自定义页面各区域组件并将各组件文件保存到Views文件夹中,每个.vue文件都是单独的组件,路由中指定的组件通过导入语句
布局使用了element-ui的container布局容器:el-container 外层容器;el-header 顶栏容器;el-aside 侧边栏容器 ;el-menu导航区域;el-main 主要区域容器;el-footer底栏容器
样式设计如下:
在el-menu导航里添加router属性实现菜单路由的动态渲染;首页导航菜单使用element-ui的NavMenu导航菜单控件。使用属性unique-opened:保证每次点击菜单只有一个菜单的展开。使用router属性,在激活导航时以 index 作为 path 进行路由跳转。
通过el-dropdown的@command点击菜单项触发的事件回调方法绑定el-dropdown-item中的command,实现注销登陆和进入个人中心功能。
elemet的MessageBox弹框实现注销登陆提示弹框。退出登陆后清除vuex中的菜单信息。
使用el-breadcrumb面包屑控件实现显示当前页面的路径,快速返回之前的任意页面功能。对于非首页的页面v-if="this.$router.currentRoute.path!=='/home'"显示层级:首先/当前页。
对于首页v-if="this.$router.currentRoute.path==='/home'",显示欢迎字体。
云办公
{{ user.name }}
个人中心
设置
注销登录
{{ item.name }}
{{ children.name }}
首页
{{ this.$router.currentRoute.name }}
欢迎来到云办公系统!
忽略hidden属性
:key="index" v-if="!item.hidden"> /home路由从首页获取 添加样式 系统管理/基础信息设置设计如下几个模块:部门管理、职位管理、职称管理、奖惩规则、权限组 使用element的Tabs标签页完成不同业务功能的切换;分隔内容上有关联但属于不同类别的数据集合。 abs 组件提供了选项卡功能,默认选中第一个标签页,你也可以通过 value 属性来指定当前选中的标签页。 在我们开发的过程中会遇到很多可以重复使用的代码块,而Vue则提供了这样的封装方式也就是Vue.component。利用组件化开发,将部门管理、职位管理、职称管理、奖惩规则、权限组等使用组件方式引入。组件也是.vue文件。组件导入方式 import 组件名 from “组件路径”,示例: import DepMana from "@/components/sys/basic/DepMana";导入后并不能直接使用,需要在components对象中注册组件。之后是组件的应用: 组件目录 为了使用方便,一次性加载所有的部门。 样式设计:flex布局,space-between:两端对齐,与父元素对齐宽度。 搜索框过滤节点的方法,通过filterNode方法传入两个参数,value-搜索输入的值,data树形标签绑定的数据。value为空时展示所有标签值,否则,判断输入的value能否在data.name(展示在树形标签上的值)找到,这里用了js查找字符串方法indexOf,返回查找元素的下标,能找到返回下标(>=0) expand-on-click-node仅当鼠标点击展开按钮时展开,方便添加和删除功能的使用。 点击按钮时获取当前节点的数据即要添加子部门的“上级部门”id(parentId) 通过el-dialog编辑按钮修改职位名称。绑定弹出框显示方法:visible.sync="dialogVisible",取消时dialogVisible=false,点击“编辑”时dialogVisible=true。 批量删除。通过multipleSelection数组获取多选数据,multipleSelection为空时,批量删除按钮禁用。提示框内通过multipleSelection展示多选信息 接口数据返回信息 键盘事件@keydown.enter.native="addPosition"输入后自动调用”添加“按钮绑定的方法。 编辑职位信息后:刷新列表数据,关闭弹框。 使用数据的拷贝Object.assign(this.updatePos, data),将data中数据赋值给updatePos,避免浅拷贝引发的updatePos对data的数据修改。 职称管理实现了职称的添加、更新、单条删除、批量删除功能。 单条更新里是否启用按钮使用了element的开关控件 JobLevelMana.vue 样式设计:由外到内依次使用了el-collapse折叠面板-》el-card卡片-》el-tree树形控件 ROLE_ 使用element折叠面板展示角色,使用的是折叠面板的手风琴模式accordion,每次只能展开一个面板。 后端获取所有用户角色接口 与接口返回的nameZh角色字段绑定,展示在折叠面板上 折叠面板每个角色的菜单访问权限,采用树形控件设置角色权限。el-tree添加show-checkbox属性展示可选框。 默认选中的角色菜单列表根据角色rid获取后端接口返回的菜单selectedMenus。通过:default-checked-keys方式绑定。 使用getCheckedKeys获取选中节点key组成的数组。let selectedKeys = tree.getCheckedKeys(true) // 获取选中的节点数组,true 仅返回被选中的叶子节点的 keys,如三级分类 可以通过搜索操作员的名字,来单独显示操作员的信息。展示所有操作员的时候,不会把自己当前登录的操作员显示出来。 操作员涉及了权限:操作员拥有哪些角色,在根据角色再去拥有哪些菜单的权限。 获取操作员管理后端信息返回 一、展示所有员工 二、分页展示 三、员工搜索 四、员工添加 五、更新和删除 六、导入导出数据 axios本身不提供下载功能,需要安装js-file-download npm install js-file-download 以流的形式输出,流的格式是二进制数组。与axios的接口请求类似,js-file-download也需要封装请求拦截器和响应拦截器,因为js-file-download不共用axios封装的拦截器功能。请求拦截器需要重新设置对请求头Authorization的设置。axios的响应拦截器是对响应码进行判断,而js-file-download需要判断返回的是否是json字符串。通过判断返回头中的content-type,如果content-type是application/json格式,则是普通的json返回,需要将二进制编码转为普通的string形式。非json字符串才是流的形式返回,需要获取fileName,contentType。为了防止可能因为文件名是中文而造成乱码,需要将fileName进行格式转换。 树形结构 安装npm install --save stompjs 将GitHub上的开源项目与自身项目进行整合来实现即时聊天功能 简介 一个基于Vue + Webpack构建的简单chat示例,聊天记录保存在localStorge。简单演示了Vue的 component、filter、directive、computed以及组件间的事件通讯。 原项目目前存在一个Bug:打开项目关闭浏览器再次打开会报错。这里使用在此项目基础上重构的项目 来与我们项目进行整合. 下载(用chrom打开下载) 地址: https://github.com/is-liyiwei/vue-Chat-demo 将下载下来的项目所在的文件,加入到本项目中。 在这里插入图片描述 assets:是网页所需要的图片,这个不需要,因为后端提供了图片,更改代码直接从后端获取。 componts:在自己的目录下创建该目录下的几个文件,复制过去。 vuex:是stroy,将其中的的代码,加入到本项目的story/index.js main.js:就是一个普通的入口,不需要加入项目当汇总。 {{user.name}} {{ item.name }}
{{ entry.date | time }}
{{ entry.content }} 前端地址:https://github.com/OneDayInMarch/yeb-front 后端地址:GitHub - OneDayInMarch/yeb-back: 云办公后台系统6.5 更新路由router/index.js
忽略router/index.js的hidden:true的
import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from "@/views/Login";
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Login',
component: Login,
hidden: true // 不会被循环遍历出来
}
]
const router = new VueRouter({
routes
})
export default router
6.6 index.html消除边距
七、基础信息设置
7.1 样式设计
Tabs 标签页
7.2 组件化开发
7.3 SysBasic.vue
7.4 部门管理DepMana.vue组件
{{ pname }}
7.5 职位管理PosMana.vue组件
element的表格控件,第一列做多选框,将其type="selection"。表格绑定多选事件@selection-change="handleSelectionChange"
PosMana.vue
7.6 职称管理JobLevelMana.vue组件
7.7 权限组PositionMana.vue组件
八、操作员管理
SysAdmin.vue
九、员工资料
let fileDownload = require('js-file-download') // 插件
let fileName = headers['content-disposition'].split(';')[1].split('filename=')[1]//文件名
let contentType = headers['content-type'] // 响应类型
fileName = decodeURIComponent(fileName) // 格式转换 防止乱码
fileDownload(resp.data, fileName, contentType) // 通过插件下载文件
EmpBasic.vue
十、工资账套管理
SalSob.vue
十一、员工账套设置
SalSobCfg.vue
基本工资
{{ scope.row.salary.basicSalary }}
交通补助
{{ scope.row.salary.trafficSalary }}
午餐补助
{{ scope.row.salary.lunchSalary }}
奖金
{{ scope.row.salary.bonus }}
养老金比率
{{ scope.row.salary.pensionPer }}
养老金基数
{{ scope.row.salary.pensionBase }}
医疗保险比率
{{ scope.row.salary.medicalPer }}
医疗保险基数
{{ scope.row.salary.medicalBase }}
公积金比率
{{ scope.row.salary.accumulationFundPer }}
公积金基数
{{ scope.row.salary.accumulationFundBase }}
十二、聊天功能
整合项目
components
card.vue
list.vue
message.vue
usertext.vue
十三、个人中心
AdminInfo.vue
用户昵称:
电话号码:
手机号码:
用户地址:
十四、源代码