Vue全家桶-电商后台管理系统项目开发

项目效果展示:

 1. 项目概述

1.1 电商项目基本业务概述

一般情况下客户使用的业务服务包括:PC端,小程序,移动web,移动app。

管理员使用的业务服务:PC后台管理端;

  • PC后台管理端的功能

管理用户账号(登录,退出,用户管理,权限管理),商品管理(商品分类,分类参数,商品信息,订单),数据统计;

  •  开发模式  

本项目(电商后台管理系统)采用 前、后端分离 的开发模式。

前端项目是基于 Vue 的 SPA(单页应用程序)项目;

  • 本项目技术选型

前端项目技术栈()

  • Vue
  • Vue-Router
  • Element-UI
  • Axios
  • Echarts

后端项目技术栈

  • Node.js
  • Express
  • Jwt(模拟session);
  • Mysql
  • Sequelize(操作数据库的框架)

Vue全家桶-电商后台管理系统项目开发_第1张图片

 1.2 电商后台管理系统的功能

          电商后台管理系统用于管理用户账号、商品分类、商品信息、订单、数据统计等业务功能。

Vue全家桶-电商后台管理系统项目开发_第2张图片

1.3 电商后台管理系统的开发模式(前、后端分离)

       电商后台管理系统整体采用前后端分离的开发模式,其中前端项目是 基于 Vue 技术栈的 SPA 项目 。在这里插入图片描述

什么是 前后端分离 的开发模式?

  • 前端:主要 负责绘制页面,同时,基于 Ajax 技术,调用后端提供的 API 接口
  • 后端:主要负责 操作数据库,并且向前端 暴露 API 接口

前、后端分离的开发模式,是目前 主流 的 开发模式 。

优点: 开发效率高、项目易于维护。

在这里插入图片描述

2. 项目初始化

2.1 前端项目初始化步骤

  1. 安装 Vue 脚手架Vue全家桶-电商后台管理系统项目开发_第3张图片

    安装 Vue CLI 交互式项目脚手架(一个基于 Vue.js 进行快速开发的完整系统)。

  2. 1)cmd 中执行以下命令安装 Vue CLI 包:

    npm install -g @vue/cli
    
    

    2)安装完成后,检查版本是否正确:

    vue --version
    

    Vue CLI 的包名称由 vue-cli 改成了 @vue/cli。 如果你已经全局安装了旧版本的 vue-cli (1.x 或 2.x),你需要先通过 npm uninstall vue-cli -g 或 yarn global remove vue-cli 卸载它。

Node 版本要求:
Vue CLI 4.x 需要 Node.js v8.9 或更高版本 (推荐 v10 以上)。你可以使用 n,nvm 或 nvm-windows 在同一台电脑中管理多个 Node 版本。

2. 通过 Vue 脚手架创建项目(本项目开发采用 “ 可视化面板 ” 创建)

1)cmd 终端中输入 :

vue ui

Vue全家桶-电商后台管理系统项目开发_第4张图片

 运行完成后,自动打开如下页面:
在这里插入图片描述

2)点击 “ + 创建 ” 进入到目录选择面板,选择目录后。再点击 “ + 在此创建新目录 ”按钮。

填写项目信息:
Vue全家桶-电商后台管理系统项目开发_第5张图片
3)进入“ 预设 ”面板,并按如下图示勾选:
Vue全家桶-电商后台管理系统项目开发_第6张图片

4)点击下一步,进入“ 功能 ”选择面板:

Vue全家桶-电商后台管理系统项目开发_第7张图片

 上图中,勾选了 “ 使用配置文件 ” 后,就会将不同的配置 单独 地存放为一个配置文件。点击 下一步,打开 配置 面板。

5)完成如下操作:Vue全家桶-电商后台管理系统项目开发_第8张图片

6)单击 下一步。提示是否保存新预设(方便下次直接选择该配置 / 也可不保存)。

Vue全家桶-电商后台管理系统项目开发_第9张图片

 点击 “保存预设并创建项目” 按钮后,系统自动创建项目如下:

Vue全家桶-电商后台管理系统项目开发_第10张图片

3. 配置 Vue 路由

在上面步骤中已自动配置。

4. 配置 Element-UI 组件库:在插件中安装,搜索vue-cli-plugin-element

1)打开“仪表盘”,单击左侧 “ 插件 ”按钮,再单击右上角的 “ + 添加插件 ”

Vue全家桶-电商后台管理系统项目开发_第11张图片

2)搜索插件 vue-cli-plugin-element 并安装。
Vue全家桶-电商后台管理系统项目开发_第12张图片

 

3)跳转到 “ 配置插件 ”面板,操作如下:
Vue全家桶-电商后台管理系统项目开发_第13张图片

5. 配置 axios 库:在依赖中安装,搜索axios(运行依赖)

1)点击 左侧边栏 “ 依赖 ” 按钮,再点击右上角 “ 安装依赖 ”
Vue全家桶-电商后台管理系统项目开发_第14张图片

 

2)安装依赖

Vue全家桶-电商后台管理系统项目开发_第15张图片

6. 初始化 git 远程仓库

7. 将本地项目托管到 Github 或 码云中(方便团队成员协作开发)

码云相关操作

1. 注册登录码云账号,注册地址:https://gitee.com/signup
Vue全家桶-电商后台管理系统项目开发_第16张图片

2. 安装 git

在Windows上使用 Git,可以从Git 官网直接下载安装程序进行安装。

测试:git --version(终端中打印出版本号 即为安装成功 )

3. 点击网站右上角“登录”,登录码云,并进行账号设置
Vue全家桶-电商后台管理系统项目开发_第17张图片

 Vue全家桶-电商后台管理系统项目开发_第18张图片

下一步:

Vue全家桶-电商后台管理系统项目开发_第19张图片


下一步:
Vue全家桶-电商后台管理系统项目开发_第20张图片

4. 在本地创建公钥(终端中运行如下命令)

ssh-keygen -t rsa -C "[email protected]"

 :上述命令(示例)中的 “ [email protected]” 字样,请务必替换为自己注册 gitee 时的真实邮箱后,再回车执行!

Vue全家桶-电商后台管理系统项目开发_第21张图片

 然后回车,接着连敲 3 次回车(中间不需任何操作)即可生成公钥。如图:

5. 找到公钥地址

Your identification has been saved in /c/Users/My/.ssh/id_rsa;
Your public key has been saved in /c/Users/My/.ssh/ id_rsa.pub。

当创建公钥完毕后,请注意打印出来的信息“Your public key has been saved in”


/c/Users/My/.ssh/id_rsa.pub : c盘下面的Users下面的My下面的.ssh下面的 id_rsa.pub 就是创建好的 公钥 了。

6. 用 记事本 或其它编辑器打开id_rsa.pub文件,复制文件中的所有代码:

Vue全家桶-电商后台管理系统项目开发_第22张图片

 再点击码云中的 SSH 公钥按钮,将复制好的的公钥粘贴到公钥文本框中。

Vue全家桶-电商后台管理系统项目开发_第23张图片

 点击”确定“按钮,再根据提示输入验证密码后,即完成ssh公钥添加:

Vue全家桶-电商后台管理系统项目开发_第24张图片

7.  测试公钥是否添加成功

在完成 gitee 设置中添加公钥后,再 cmd 终端中输入:

ssh -T [email protected]

过程中出现如下图所示的询问(是否继续连接?)时,输入 “yes” 回车继续,直到命令执行完成。

在这里插入图片描述

 首次使用需要确认并添加主机到本机SSH可信列表。若返回 Hi XXX! You’ve successfully authenticated, but Gitee.com does not provide shell access. 内容,则证明添加成功。如下图所示:

Vue全家桶-电商后台管理系统项目开发_第25张图片

 再次运行命令ssh -T [email protected],同样也可看到如下所示信息:
Vue全家桶-电商后台管理系统项目开发_第26张图片

8. 将本地代码托管到码云中

点击码云右上角的+号 -> 新建仓库

Vue全家桶-电商后台管理系统项目开发_第27张图片

 Vue全家桶-电商后台管理系统项目开发_第28张图片

9. 进行git配置

注:执行如下命令前,必须确保本机已安装过 git,否则终端中会 报错 。

Vue全家桶-电商后台管理系统项目开发_第29张图片

10 项目首次提交

1)检查状态:项目根目录下输入以下命令

git status

运行结果显示项目中存在未跟踪的文件没有被提交 ,如下所示:Vue全家桶-电商后台管理系统项目开发_第30张图片

此时需要做一下处理,即把所有的文件都添加到 暂存区

2)添加到 暂存区:运行如下命令:

git add .

注意:命令中的 add 和后面的.(小圆点)中间有个空格,否则会报错。

3)本地提交:将暂存区中的文件提交至 本地仓库中 :

git commit -m "add files"

再次检查状态:

git status

运行结果如下:
在这里插入图片描述

提示当前 “ 处于主分支,工作目录是干净的 ”,即没有要提交的文件。

但当前的这些操作只是在本地操作仓库,仓库还没上传到码云中,

4)将本地仓库与远程 git仓库 关联

找到并在终端中运行(你新建的码云仓库 vue_shop 页面最底部提供的那两句)代码,如下所示:

git remote add origin https://gitee.com/XXXXX/vue_shop.git
git push -u origin master

注: XXXX 为你的码云 帐户名称 ( 非邮箱名称)。如果运行 报错,请点击 这里 查看解决办法。

执行第二句命令时,会弹出如下安全验证,输入用户名和密码确认后,等待完成提交即可。
Vue全家桶-电商后台管理系统项目开发_第31张图片

 说明:如果是第一次向码云中提交代码,会弹出码云的帐号和密码输入窗口(以后不会再出现)

5)检查是否上传(远程仓库)成功

在远程仓库中点击 “刷新”,即可看到提交信息
Vue全家桶-电商后台管理系统项目开发_第32张图片

类似这样,表示本地仓库已成功上传到了码云中。

2.2 后台项目的环境安装配置

2.2.1 安装 MySQL 数据库

① 安装素材中提供的 phpStudy ,傻瓜式安装。

② 将素材中的压缩包解压,记住解压路径。
 

Vue全家桶-电商后台管理系统项目开发_第33张图片

③ 运行phpStudy,单击“ MySQL管理器 ” 按钮,选择 MySQL导入导出 菜单项。
④ 按上图所示,找到对应路径下已解压得到的 db 文件夹中的 mydb.sql 数据库脚本文件,点击 “ 导入” 按钮,自动弹出黑色的命令行窗口,开始还原数据库(此时间稍长,请耐心等待~);
温馨提示! 还原结束时,黑色的命令行窗口会自动关闭,此时可按如下所示查看生成的数据库。
Vue全家桶-电商后台管理系统项目开发_第34张图片
如在数据库目录下能够看到如下图所示的路径、文件,表示 数据库还原成功!在这里插入图片描述

注: 由于开发过程中不需要用到 Apache,可将其 “ 停止 ” 服务,如下图所示:Vue全家桶-电商后台管理系统项目开发_第35张图片

2.2.2 配置后台项目

在前面已经解压出来的 vue_api_server,就是后台 API 项目 。但需要先 安装依赖包 才能正常运行。

A. 安装 nodeJS 环境,配置后台项目

B. 安装项目依赖包

进入 vue_api_server 目录中,shift+右键 在弹出的菜单中选择 “在此处打开 Powershell 窗口 ” 打开终端,输入命令安装项目依赖包:

npm install

C.启动项目

继续在终端中输入如下命令,启动项目:

node .\app.js

注意:启动前,必须先将 phpStudy 的 MySQL 服务开启。

D. 使用 postman 测试 API 接口是否正常。

安装 postman 软件(点此下载),启动 PostMan 填写相关参数(首次使用该软件需进行简单注册),如下所示:


Vue全家桶-电商后台管理系统项目开发_第36张图片

注意:输入登录请求地址用户字段名密码字段名时,请务必与 API 文档保持一致;

点击 “ Send ” 后,服务端返回如下信息:

Vue全家桶-电商后台管理系统项目开发_第37张图片

 电商管理后台 API 接口文档 下载:https://pan.baidu.com/s/1OGxh05B0BocQm9cP3BWO7w  提取码:

3. 登录 / 退出 功能

3.1 登录概述

1. 登录业务流程

  • 在登录页面输入用户名和密码

  • 调用后台接口进行验证

  • 通过验证之后,根据后台的响应状态跳转到项目主页

2. 登录业务的相关技术点

  • http 是无状态的;

  • 通过 cookie 在客户端记录状态;

  • 通过 session 在服务器端记录状态;

  • 通过 token 方式维持状态(推荐垮域 时采用)

3.2 登录 - token 原理分析

Vue全家桶-电商后台管理系统项目开发_第38张图片

3.3 实现登录功能

  • 一、登录逻辑:

    在登录页面输入账号和密码进行登录,将数据发送给服务器 ==> 服务器返回登录的结果,登录成功则返回数据中带有token ==> 客户端得到 token 并进行保存,后续的请求都需要将此 token 发送给服务器,服务器会验证 token 以保证用户身份。

二、登录状态保持

1)如果服务器和客户端 同源 1,建议可以使用cookie或者session来保持登录状态;

2)如果客户端和服务器 跨域 2,建议使用token进行维持登录状态。

http://www.123.com/index.html 调用 http://www.123.com/abc.do ( 非跨域 )
http://www.123.com/index.html 调用 http://www.456.com/abc.do ( 主域名不同:123/456,跨域 )
http://abc.123.com/index.html 调用 http://def.123.com/server.do ( 子域名不同:abc/def,跨域 )
http://www.123.com:8080/index.html 调用 http://www.123.com:8081/server.do( 端口不同:8080/8081,跨域 )
http://www.123.com/index.html 调用 https://www.123.com/server.do ( 协议不同:http/https,跨域 )

因合作方域名与我方域名不同,当从合作方加载页面调用我方接口时,会出现跨域的报错

三、添加新分支 login,在 login分支 中开发当前项目 vue_shop

1)项目根目录中打开 vue_shop 终端(shift + 右键 通过 vs code打开),使用git status命令确定当前项目状态(是否干净)。

git status

运行结果如下所示:
Vue全家桶-电商后台管理系统项目开发_第39张图片

表明当前工作区是干净的,可以进行登录页面的绘制。

—— 此时需要创建一个新分支。

2)确定当前工作目录是干净的之后,创建一个新分支并切换到该分支进行开发,开发完毕之后将其合并到 master

git checkout -b login

注: 在开发中,只要进行一个新功能开发的时候,尽量把它放到一个新分支上,当这个功能开发完毕后,再把它合并到主分支 master 上。

3)然后git branch命令查看新创建的分支,确定我们正在使用 login分支 进行开发。

在这里插入图片描述

 绿色 表示当前所处的分支。

4)接着,执行vue ui命令打开 ui 界面,然后运行 serve,运行 app 查看当前项目效果。

Vue全家桶-电商后台管理系统项目开发_第40张图片

四、登录页面的布局

点击 “ 启动App ” ,打开项目:
Vue全家桶-电商后台管理系统项目开发_第41张图片

此时,我们可以看到现在它只是一个默认页面,需要把它重置为空白页面:

1)打开项目的 src 目录,点击查看main.js文件(这是整个项目的 入口文件):

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import './plugins/element.js'

Vue.config.productionTip = false

new Vue({
	// 把 router 路由挂载到实例
	router,
	// 通过 render 函数,把 App 根组件渲染到页面上
	render: h => h(App)
}).$mount('#app')

2)再打开 App.vue (根组件),将根组件的内容进行清理(template 中只留下根节点,script 中留下默认导出,去掉组件,style 中去掉所有样式),清理完成后如下所示:






3)再打开路由文件夹下的 index.js(有些版本的 Vue ui 所创建的工程项目,其 router 文件夹下的路由文件名为router.js),将routes数组中默认的路由规则全部清除,然后将views删除:

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

export default new Router({
	routes: [
    
	]
})

五、新建 Login.vue 组件

1)将文件夹components中的helloworld.vue删除,并新建 Login.vue 单文件组件,添加 templatescriptstyle 标签,style 标签中的 scoped 可以防止组件之间的样式冲突(没有scoped则样式是全局的)。






scoped:是 vue 指令,用来控制组件生效的范围(表示只在当前组件内生效,只要是单文件组件,都应加上)

:当添加背景样式并保存代码修改后,浏览器会报错 “ 找不到 less-loader”,如下图所示:

在这里插入图片描述

 这是由于 Vue 的 cli 工具创建的项目默认并没有安装 less 相关的 loader,如果要使用 less 语法(如

其中,有用到以下内容,需要进行进一步处理:

Ⅰ. 添加 element-ui 的表单组件

在 plugins 文件夹中打开 element.js 文件,进行 elementui 的按需导入:

import Vue from 'vue'
import { Button } from 'element-ui'
import { Form, FormItem } from 'element-ui'
import { Input } from 'element-ui'

Vue.use(Button)
Vue.use(Form)
Vue.use(FormItem)
Vue.use(Input)

Ⅱ. 添加第三方字体

复制素材中的 fonts 文件夹到 assets 中,在入口文件 main.js 中导入:

import './assets/fonts/iconfont.css'

然后直接 

接着添加登录盒子

Ⅲ. 添加表单验证的步骤

1)给添加属性:rules="rules"rules 是一堆验证规则,定义在 script 中。

2)在 script 中添加 rules:export default{ data(){return{…, rules: {

name: [
        { required: true, message: '请输入活动名称', trigger: 'blur' },
        { min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
      ],
      region: [
        { required: true, message: '请选择活动区域', trigger: 'change' }
      ]

3)通过的 prop 属性设置验证规则

4)导入axios 以发送 ajax 请求

打开main.js,导入 axios:

import axios from 'axios';

设置请求的根路径:

axios.defaults.baseURL = 'http://127.0.0.1:8888/api/private/v1/';

挂载axios:

Vue.prototype.$http = axios;

5)配置弹窗提示

在 plugins 文件夹中打开 element.js 文件,进行 elementui 的按需导入:

import {Message} from 'element-ui'

进行全局挂载:

Vue.prototype.$message = Message;

在 login.vue 组件中编写弹窗代码:

this.$message.error('登录失败')

六、登录成功之后的操作

实现思路:

1.将登录成功之后的 token ,保存到客户端的 sessionStorage 中;

      原因如下:

  • 项目中除了 登录 以外的其它 API 接口 ,必须在登录之后才能访问(访问接口时提供 token,表明已登录);
  • token 只应在当前网站打开期间生效,所以将 token 保存在 sessionStorage 中。
  • 之所以保存在 sessionStorage 而不是 localStorage 中,是因为localStorage是持久化的存贮机制,而sessionStorage是会话期间的存贮机制。

2.通过 编程式导航 跳转到后台主页,路由地址是 /home (编程式导航:通过 $router对象,调用 push 方法来发生跳转)。

代码实现

A. 保持用户token信息

要保存 token ,先要能访问到它:

console.log(res)

Vue全家桶-电商后台管理系统项目开发_第79张图片

 可以看到 res 上有个 data 属性,data 属性中包含 token字符串,可以调用sessionStorage.setItem这个 API 接口,将这个 token 保存在 sessionStorage 中:

window.sessionStorage.setItem('token', res.data.token)

括号中的参数是键值对的形式(键:token ,值:res.data.token)。

因此,当登录成功之后,我们将后台返回的 token 保存到 sessionStorage 中,操作完毕之后,需要跳转到/home目录:

this.$router.push('/home')

此时 login 方法的代码如下:

login () {
	this.$refs.loginFormRef.validate(async valid => {
		// console.log(valid)
		if (!valid) return false
		const { data: res } = await this.$http.post('login', this.loginForm) // eslint-disable-line no-unused-vars
		// console.log(res)
		if (res.meta.status !== 200) return this.$message.error('登录失败!')
		this.$message.success('登录成功!')
		// console.log(res)
		window.sessionStorage.setItem('token', res.data.token)
		this.$router.push('/home')
	})
}

调试运行程序,当点击登录后,Application 里的 session Storage 中保存到了 token 值。同时,通过这次 编程式导航,发生了页面跳转。如下所示:

Vue全家桶-电商后台管理系统项目开发_第80张图片
但此时的 home 页面是空白的。

创建 home 页面并完善路由规则

1)创建 home 页面:在 components 目录中,新建一个 Home.vue 组件文件;

Vue全家桶-电商后台管理系统项目开发_第81张图片
修改完毕再次打印时,可发现 result 已不再是一个 Promise 对象,而是一个具体的响应对象,对象中包含了 6 个属性,都是 axios 帮我们封装好的,其中,data 才是服务器返回的真实数据(其它 5 个属性我们不需要),如下图所示: 

 2)用 template 标签书写好基本结构代码:






3)在路由文件夹下的index.js中导入组件并添加 路由规则

import Home from '../components/Home.vue'

export default new VueRouter({
    routes: [
        { path: '/', redirect: '/login' },
        { path: '/login', component: Login },
        { path: '/home', component: Home }
    ]
})

路由导航卫士控制页面访问权限

当前“ /home ” 所对应的页面只有在登录的时候才允许被访问。

因此,如果用户未登录,直接通过 URL 访问特定(需要权限)的页面,则需要重新导航(即强制跳转 )到登录页面。

那么,如何进行导航 ?

这就需要用到路由 导航守卫:为路由对象 router 调用一个 beforeEach 函数,这个 beforeEach 就叫做 导航守卫 。

router.beforeEach ((to, from, next) => { })

该函数接收一个 回调函数,包括 个行参,分别为tofromnext,其中:

  • to:将要访问的路径;
  • from:从哪个页面跳转过来;
  • next:放行的一个函数,next()表示直接放行;next('/login')表示强制跳转。

路由导航卫士的用法

判断 to 对应的地址是否为/login

  • 如果是,则表示用户要访问登录页,而登录页是不需要权限的,这时就直接调用 next 函数(即 return next())放行,允许访问登录页;
  • 如果不是,则要判断 sessionStorage 中是否存在 token。

先把 token 取出来,然后判断是否有 token ,如果没有 token,证明用户没有登录,此时需要强制跳转到登录页(/login),让用户登录后再进行访问。如果有 token 则直接放行(next ())


代码实现(导航跳转):

打开路由所对应的文件(有些版本的 Vue ui 生成的路由文件名是 router.js),我这里是 index.js,我们在前面已完成的代码:

import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from '../components/Login.vue'
import Home from '../components/Home.vue'

Vue.use(VueRouter)

export default new VueRouter({
    routes: [
        { path: '/', redirect: '/login' },
        { path: '/login', component: Login },
        { path: '/home', component: Home }
    ]
})

这里需要对代码进行改造,当前export default new VueRouter({}) 表示是直接 new 了一个 VueRouter 对象并默认导出。
此时需要将 export default 和 VueRouter拆分开,先拿到 VueRouter 对象,给它挂载一个 导航守卫,然后再用 export default 暴露出去。修改如下:

const router = new VueRouter({
	routes: [
		{ path: '/', redirect: '/login' },
		{ path: '/login', component: Login },
		{ path: '/home', component: Home }
	]
})

// 暴露路由对象之前,要挂载路由守卫
router.beforeEach((to, from, next) => {
    if (to.push === '/login') return next()
    // 获取 token
    const tokenStr = window.sessionStorage.getItem('token')
    if (!tokenStr) return next('/login')
    next()
})

export default router

3.4 实现退出功能

1、实现原理

基于 token 的方式实现 退出 比较简单,只需要 销毁本地的 token 即可。这样,后续的请求就不会携带 token ,必须重新登录生成一个新的 token 之后才可以访问页面。


2、功能实现

在 Home 组件中添加一个退出功能按钮,给 退出按钮 添加 点击事件,添加事件处理代码如下:

export default {
    methods:{
        logout(){
        	// 清空token
            window.sessionStorage.clear();
            // 跳转到登录页
            this.$router.push('/login');
        }
    }
}

处理 ESLint 警告

补充

A、处理 ESLint 警告

打开脚手架面板,查看 警告 信息

默认情况下,ESLint 和 VS code 格式化工具有 冲突,需要添加配置文件解决冲突。

1)在项目根目录新建 .prettierrc.json 文件(注意prettierrc前面有小点)

{
	"semi":false,  // 结尾处的分号(;)
    "singleQuote":true  // 单引号
}

2)打开.eslintrc.js文件,禁用对 space-before-function-paren 的检查:

rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
    'space-before-function-paren' : 0
  },

3)*其它方法(注:此方法来源于网络,未亲测!仅记录于此供参考)

如果在使用 vue-cli 创建项目时已经选择了 babeleslint,那么只需要安装缺少的包:

npm i prettier prettier-eslint --save-dev

这样也能得到正确的格式,其原理是先把代码用 prettier 格式化,然后再用 ESLint fix。

B、合并按需导入的 element-ui

import Vue from 'vue'
import { Button, Form, FormItem, Input, Message } from 'element-ui'

Vue.use(Button)
Vue.use(Form)
Vue.use(FormItem)
Vue.use(Input)
// 进行全局挂载:
Vue.prototype.$message = Message

C.将代码提交到码云

① 新建一个项目终端,输入命令查看修改过的或新增的文件内容:

git status

② 将所有文件添加到暂存区:

git add.

此时,所有文件变成绿色,表示已经都添加到了暂存 区

③ 将所有代码提交到本地仓库:

git commit -m "添加登录功能以及/home的基本结构"

④ 查看所处分支(所有代码都被提交到了 login 分支):

git branch  

⑤ 将 login 分支代码合并到 master 主分支:

a、先切换到 master

git checkout master

b、再 master 分支进行代码合并:

git merge login

⑥ 将本地最新的 master 推送到远端的码云:

git push

打开码云中的仓库如下图(表示已把本地的master 分支推送到了云端仓库中进行了保存)。

Vue全家桶-电商后台管理系统项目开发_第82张图片

 ⑦ 推送本地的子分支到码云

如下图所示,当前云端中只有一个 master 分支,并没有 login 子分支:

Vue全家桶-电商后台管理系统项目开发_第83张图片

因此还需要将 login 分支推送到云端:

a. 先切换到子分支:

git checkout 分支名

b. 然后推送到码云:

此时如果直接用 git push 推送是不会成功的,因为云端并没有记录 login 子分支。

由于是首次把 login 分支推送到云端分支,此时,需要在 push 加上一个参数 -u,完整命令如下:

git push -u origin 远端分支名

刷新后,即可看到仓库中多了一个 login 子分支:Vue全家桶-电商后台管理系统项目开发_第84张图片

关于推送

我们写的源代码,经过测试之后没问题,一定要先合并到主分支,然后再将主分支推送到云端仓库中,同时,也不要忘了再把新建的子分支推送到云端仓库中。在这里插入图片描述

4. 主页布局

  • 实现后台首页的基本布局
  • 实现左侧菜单栏
  • 实现用户列表展示
  • 实现添加用户

4.1 后台首页基本布局

Vue全家桶-电商后台管理系统项目开发_第85张图片

整体布局: 先上下划分,再左右划分。
 

借助 Element UI 中的布局容器进行布局:

  1. 进入官网 ,找到 Container 布局容器组件:Vue全家桶-电商后台管理系统项目开发_第86张图片

     

  2. 找到符合主页设计图的样式:Vue全家桶-电商后台管理系统项目开发_第87张图片

     

  3. 找到该布局结构的代码,展开后复制粘贴到项目中

基本布局:打开 Home.vue 组件

  • 原来 Home.vue 文件中的结构代码:

    
    

    修改为官方提供的布局容器的结构:

    
    

    保存后,打开页面并没有看到想要的效果,并且终端里有报错,如下图所示:在这里插入图片描述

     

    这是因为我们还没有注册 el-container 这些组件。

    plugins 目录下的 element.js 中导入组件:Vue全家桶-电商后台管理系统项目开发_第88张图片

     保存后,页面效果如下图:Vue全家桶-电商后台管理系统项目开发_第89张图片

     

    此时,虽然很丑,但是已初具雏形,并且也解决了报错问题。

    接下来,在 Home.vue 文件中的  样式区域标签内,写上:

    .iconfont {
        margin-right: 10px;
    }
    

2)每次只能展开一个菜单项并解决边框问题

  • ① 解决多个菜单项能同时展开的问题Vue全家桶-电商后台管理系统项目开发_第117张图片

 【问题】:当前所有的菜单都能被同时展开,而实际需求只允许每次展开一个,其余的折叠。

【解决】

这个在 Element UI 官方的 NavMenu导航菜单 组件中,为 提供了unique-opened 属性,其值类型为布尔值,默认值为 false,即,可同时展开若干菜单项。

因此,为了保持左侧菜单每次只能打开一个,显示其中的子菜单,可在 el-menu 中添加一个属性 unique-opened;Vue全家桶-电商后台管理系统项目开发_第118张图片

 把 unique-opened 属性值重置为 true 即可实现(每次只展开一个菜单项)。添加属性并重置为 true 如下:Vue全家桶-电商后台管理系统项目开发_第119张图片

注: 或者也可以数据绑定进行设置(此时true认为是一个bool值,而不是字符串) :unique-opened="true"

这样就实现了每次只展开唯一一个菜单项的效果,如下图所示:Vue全家桶-电商后台管理系统项目开发_第120张图片

 ② 解决边框线未对齐的问题

Vue全家桶-电商后台管理系统项目开发_第121张图片

通过检查元素,发现el-menu类的样式中,存在一个border-right,其值为 1px 的边框,如下图所示:

 通过类名选择器,将其重置为 none :

.el-aside {
    background-color:#333744;
    .el-menu {
        border-right: none;
    }
}

4.6 制作侧边菜单栏的伸缩(展开/折叠)功能

  1. 打开 Home.vue 文件,在侧边栏内部、菜单之前的上方添加一个 div 盒子:
    
    
    	
    |||
  2. Home.vue 中的

     3. 通过路由的形式,在右侧主体区展示用户列表

  • 在 router 目录里的 index.js 路由文件中,导入用户列表组件、定义路由规则:

     

    ... // 导入的其它组件
    import Users from '../components/user/Users.vue'
    
    Vue.use(VueRouter)
    
    const router = new VueRouter({
        routes: [
    		... // 其它路由规则
            {
              path: '/home',
              component: Home,
              redirect: '/welcome',
              children: [
                 { path: '/welcome', component: Welcome },
                 { path: '/users', component: Users }
                ]
            }
        ]
    })
    

     但是,此时发现激活的菜单文本并没有高亮显示:
    Vue全家桶-电商后台管理系统项目开发_第134张图片

     

    在 Menu 属性中有个 default-active 参数,表示当前激活菜单的 index 可以赋值给 default-active

    即,如果想让菜单中的某一项被激活时高亮,就把该项对应的 index 赋值给整个 Menu 菜单的属性 default-active 。
    Vue全家桶-电商后台管理系统项目开发_第135张图片

     打开 Home.vue ,在 中添加 default-active 属性,为便于测试,直接将其值写死为 /users,即default-active="/users",效果如下:
    Vue全家桶-电商后台管理系统项目开发_第136张图片

如果要把激活项的 index 换成动态的,要如何实现 ???

实现思路:

当我们点击链接时,把对应的地址先保存到 Session Storage 中。当刷新页面(即Home组件刚被创建)时,再把这个值取出来,动态的赋值给 el-menu 中的 default-active 属性 。

第一步:给所有的二级菜单绑定一个 单击事件,命名为 saveNavState,在单击事件中把 path 值存贮起来:



第二步: 定义 saveNavState 函数

// 保存链接的激活状态
saveNavState(activePath) {
	window.sessionStorage.setItem('activePath', activePath)
 }

运行程序后,即可保存path 值:

Vue全家桶-电商后台管理系统项目开发_第137张图片

 

接下来,需要把保存的值取出来


第三步: 在 data 中定义 activePath 来保存数据,默认为空:activePath: ''。再将 activePath 绑定到 的 default-active 属性上。替换原来写死的值/users。


第四步: 动态赋值

当整个 Home 组件一被创建的时候,就立即从 Session Storage 中把值取出来赋给 activePath ;

由于组件被创建时,第一时间执行的是 Created 生命周期函数,所以就直接在 Created 里进行赋值:

created() {
	this.getMenuList()
	this.activePath = window.sessionStorage.getItem('ctivePath')
}

Vue全家桶-电商后台管理系统项目开发_第138张图片

 我们发现,当点击别的链接之后,再次点击 用户列表 时,对应的链接文本并没有高亮,原因是缺少了一步。应该是点击不同链接时,也要为当前的 activePath 重新赋值( saveNavState 点击事件里):

// 保存链接的激活状态
saveNavState(activePath) {
	window.sessionStorage.setItem('activePath', activePath)
	// 点击链接时,重新赋值
	this.activePath = activePath
 }

2. 绘制用户列表基本 UI 结构

  • 面包屑导航:el-breadcrumb
  • Element-UI 栅格系统基本使用:el-row
  • 表格布局:el-tableel-pagination

在 Element UI 官方的 面包屑 导航组件中,找到对应的代码并复制。Vue全家桶-电商后台管理系统项目开发_第139张图片

 打开 Users.vue 文件,将复制好的代码粘贴到该组件文件 template 模板区中:


接下来,在element.js 中按需导入 Breadcrumb 和 BreadcrumbItem 组件并注册(否则不生效):

import Vue from 'vue'
... // 其它组件
import { Breadcrumb, breadcrumbItem } from 'element-ui'

// 注册全局组件
... // 注册的其它组件
Vue.use(Breadcrumb)
Vue.use(breadcrumbItem)

Vue.prototype.$message = Message
  • 此时,面包屑导航功能完成如下:

Vue全家桶-电商后台管理系统项目开发_第140张图片

 

绘制卡片视图区域

在 Element UI 官网 中找到 card卡片 组件,
Vue全家桶-电商后台管理系统项目开发_第141张图片

 将复制的代码粘贴到 users.vue 文件中:



	
{{'列表内容 ' + o }}

整理代码,将不需要的 for 循环和 box-card 类删掉后,结构代码如下:



	123

再在 element.js 中按需导入 card 卡片后,效果如下:
Vue全家桶-电商后台管理系统项目开发_第142张图片

 目视可见卡片离面包屑导航太近。在 assets 中的 css 目录下,找到 global.css,为卡片视图区设置上部的间距,这里通过面包屑的类名选择器 el-breadcrumb ,给面包屑增加一个 margin -bottom 值,把卡片盒子挤下来一点:

.el-breadcrumb {
    margin-bottom: 15px;
    font-size: 12px;
}

保存后,基本的效果如下图: 在这里插入图片描述
为卡片视图重置阴影样式。

.el-car {
    box-shadow: 0 1px 1px rgba(0, 0 ,0.15) !important;
}

Vue全家桶-电商后台管理系统项目开发_第143张图片

5.2.2 用户状态列和操作列处理

  • 作用域插槽
  • 接口调用

5.2.3 表格数据填充

  • 调用后台接口
  • 表格数据初填充
const { data: res } = await this.$http.get('users', { params: this.queryInfo })
if (res.meta.status !== 200) {
	return this.$message.error('查询用户列表失败!')
}
this.total = res.data.total
this.userlist = res.data.users

5.2.4 表格数据分页

分页组件用法:

  1. 当前页码:pagenum

  2. 每页条数:pagesize

  3. 记录总数:total

  4. 页码变化事件

  5. 每页条数变化事件

  6. 分页条菜单控制



5.2.5 搜索功能

   将搜索 关键字,作为 参数 添加到列表查询的参数中。


	 

5.3 用户管理-用户状态控制

  • 开关组件的用法

  • 接口调用更改用户的状态



async stateChanged(id, newState) {
	const { data: res } = await this.$http.put(`users/${id}/state/${newState}`)
	if (res.meta.status !== 200) {
		return this.$message.error('修改状态失败!')
	}
}

5.4 用户管理-添加用户

5.4.1 添加用户表单弹窗布局

  • 弹窗组件用法

  • 控制弹窗显示和隐藏


	
		
			
		
		
	
	
		取 消
		确 定
	

5.4.2 表单验证

  1. 内置 表单验证规则

	


addFormRules: {
	username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
	password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
}
this.$refs.addFormRef.validate(async valid => {
	if (!valid) return
})

自定义 表单验证规则

手机号验证规则

const checkMobile = (rule, value, cb) => {
	let reg = /^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/
	if (reg.test(value)) {
		cb()
	} else {
		cb(new Error('手机号码格式不正确'))
	}
}
mobile: [
	{ required: true, message: '请输入手机号', trigger: 'blur' },
	{ validator: checkMobile, trigger: 'blur' }
]

5.4.3 表单提交

     将用户信息作为参数,调用后台接口添加用户 。

this.$refs.addFormRef.validate(async valid => {
	if (!valid) return
	const { data: res } = await this.$http.post('users', this.addForm)
	if (res.meta.status !== 201) {
		return this.$message.error('添加用户失败!')
	}
	this.$message.success('添加用户成功!')
	this.addDialogVisible = false
	this.getUserList()
})

5.5 用户管理-编辑用户

5.5.1 根据 ID 查询用户信息



async showEditDialog(id) {
	const { data: res } = await this.$http.get('users/' + id)
	if (res.meta.status !== 200) {
		return this.$message.error('查询用户信息失败!')
	}
	// 把获取到的用户信息对象,保存到 编辑表单数据对象中
	this.editForm = res.data
	this.editDialogVisible = true
}

5.5.2 编辑提交表单

this.$refs.editFormRef.validate(async valid => {
	if (!valid) return
	// 发起修改的请求
	const { data: res } = await this.$http.put('users/' + this.editForm.id, {
		email: this.editForm.email,
		mobile: this.editForm.mobile
	})
	if (res.meta.status !== 200) {
		return this.$message.error('编辑用户信息失败!')
	}
	this.$message.success('编辑用户信息成功!')
	this.getUserList()
	this.editDialogVisible = false
})

5.6 用户管理-删除用户

在点击删除按钮的时候,应跳出提示信息框,让用户确认要进行删除操作。

如果想要使用确认取消提示框,需要先将提示信息框挂载到vue中。

  • A. 导入MessageBox组件,并将MessageBox组件挂载到实例。

Vue.prototype.$confirm = MessageBox.confirm

B. 给用户列表中的删除按钮添加事件,并在事件处理函数中弹出确定取消窗,最后再根据id发送删除用户的请求


async remove(id) {
	// 询问是否要删除
	const confirmResult = await this.$confirm('此操作将永久删除该用户, 是否继续?', '提示', {
		confirmButtonText: '确定',
		cancelButtonText: '取消',
		type: 'warning'
	}).catch(err => err)
	//如果用户点击确认,则confirmResult 为'confirm'
	//如果用户点击取消, 则confirmResult获取的就是catch的错误消息'cancel'
	if(confirmResult != "confirm"){
    	return this.$message.info("已经取消删除")
	}
	//发送请求,根据id完成删除操作
	const { data: res } = await this.$http.delete('users/' + id)
	if (res.meta.status !== 200) return this.$message.error('删除用户失败!')
	this.$message.success('删除用户成功!')
	this.getUserList()
},

6 权限管理

6.1 权限管理业务分析

   通过权限管理模块控制不同的用户可以进行哪些操作,具体可以通过角色的方式进行控制,即每个用户分配一个特定的角色,角色包括不同的功能权限。

Vue全家桶-电商后台管理系统项目开发_第144张图片

6.2 添加权限列表路由

创建权限管理组件**(Rights.vue),并在router.js添加对应的路由规则

import Rights from './components/power/Rights.vue'
......
	path: '/home', component: Home, redirect: '/welcome', children: [
		{ path: "/welcome", component: Welcome },
		{ path: "/users", component: Users },
		{ path: "/rights", component: Rights }
	]
......

6.3 添加面包屑导航

在 Rights.vue 中添加面包屑组件展示导航路径。

6.4 权限列表展示

data中添加一个rightsList数据,在methods中提供一个getRightsList方法发送请求获取权限列表数据,在created中调用这个方法获取数据。


    
    
    
    
        
    


完整的添加权限,删除权限,编辑权限功能,这里不再列出,请参照前面编写过的角色管理的代码还有接口文档完成。

获取权限列表数据

// 获取权限列表数据
async getRightsList() {
	const { data: res } = await this.$http.get('rights/list')
	if (res.meta.status !== 200) {
		return this.$message.error('获取权限列表失败!')
	}
	this.rightsList = res.data
}

 

6.5 角色列表展示

  1. 调用后台接口获取角色列表数据
  2. 角色列表展示
// 获取所有角色列表
async getRolesList() {
	const { data: res } = await this.$http.get('roles')
	if (res.meta.status !== 200) {
		return this.$message.error('获取角色列表失败!')
	}
	this.rolesList = res.data
},

6.6 用户角色分配

6.6.1 展示角色对话框

① 实现用户角色对话框布局
② 控制角色对话框显示和隐藏
③ 角色对话框显示时,加载角色列表数据

async showSetRoleDialog(userInfo) {
	this.userInfo = userInfo
	// 发起请求,获取所有角色的列表
	const { data: res } = await this.$http.get('roles')
	if (res.meta.status !== 200) {
		return this.$message.error('获取角色列表失败!')
	}
	this.rolesList = res.data
	this.setRoleDialogVidible = true
}

6.6.2 完成角色分配功能

async saveNewRole() {
	if (this.selectedRoleId === '') {
		return this.$message.error('请选择新角色后再保存!')
	}
	const { data: res } = await this.$http.put(`users/${this.userInfo.id}/role`, {
		rid: this.selectedRoleId
	})
	if (res.meta.status !== 200) {
		return this.$message.error('分配角色失败!')
	}
	this.$message.success('分配角色成功!')
	this.getUserList()
	this.setRoleDialogVidible = false
}

6.7 角色权限分配

注 解:


  1. 同源:即协议相同、域名相同、端口相同

               同源策略的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。 ↩︎

  2. 跨域:是指浏览器不能执行其它网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript实施的 安全限制

    Vue全家桶-电商后台管理系统项目开发_第145张图片

你可能感兴趣的:(前端,vue.js,node.js,javascript)