项目前期准备
1、创建Vue项目
打开服务器
打开小皮面板,由其提供的网址和初始账户密码登录面板。打开数据库,删除其原始遗留的文件,添加自己服务器中的数据库并将其导入。数据库导入完成后,进入服务器文件夹,Shift+右键打开PowerShell窗口,输入
命令node app.js
,打开服务器。
安装脚手架
打开DOS命令窗口,全局安装脚手架,安装的是Vue CLI v4.5.13版本。
npm install @vue/cli -g
创建项目
有两种可以创建Vue项目的方法
- 首先创建一个文件夹,在其中创建我的Vue项目,使用命令创建
vue create myproject
选择手动选择配置项Manually select features,除了一些默认的选项,还选择了PWA(渐进式网页应用:Progressive Web App (PWA) Support)支持、 Router和CSS Pre-processors。然后选择Vue 2.x版本,因为此项目使用的是hash模式的路由,所以不需要history模式的路由;CSS预处理选择Less,之后选择标准的ESLint + Standard config配置,后续的配置Enter就可。
2.进入DOS窗口使用命令,打开GUI,在网页上打开Vue项目管理器并创建新的项目。
vue ui
打开Vue项目管理器,并创建新的项目,配置项的选择和使用命令时创建的一样,这里就不一一赘述了。
安装element-ui
如果你是使用命令创建项目
npm add element-ui
或者在项目管理器中点击依赖→安装依赖→安装依赖→搜索element-ui→选择官方element-ui→安装依赖,即可完成element-ui的安装。
项目开始
分析项目结构
所有的代码数据基本都是放在src目录之下的。在src
目录下创建api
项目,主要用来存放一些有关数据请求的文件;assets
存放的是一些css、fonts
和images
文件;component
存放的各种组件文件,在其之下又根据项目结构创建不同的目录;plugin
目录,用来存放一些需要插入的文件,如element.js
文件;router
存放的是我们在开发过程中需要配置的各种路由;utils
目录存放的是我们在开发过程中使用到的一些工具文件;view
下存放的是一些视图文件。
本项目的view主要分为登录、主页面和一个欢迎页面。
项目开始
登录界面Login
登录页面主要包含用户名和密码两个输入框,由一个form表单构成,使用element-ui中的表单以及icon图标。 因为用户名和密码都有验证条件,给表单绑定rules属性,用来验证其用户名和密码是否正确。
required
:是否是必填项
message
:当required为false时的提示信息
trigger
和‘blur’
:当失焦时验证条件
在登录页面使用会话存储sessionStorage中的token,来验证用户名和密码。
在localStorage、sessionStorage、cookie三种存储方式中选择sessionStorage的原因:
localStorage
:本地存储,只要用户不主动清除数据,其数据则会永久存在,因此不适用本项目;
sessionStorage
:会话存储,sessionStorage存储的数据并不会失效,只有当用户关闭浏览器时,其数据则会自动清除,对于本项目来说,是非常合适的。
cookie
:cookie存储也可以用来存储用户名和密码信息,但是它每次都会携带在HTTP头中,发送给服务端,当使用cookie保存过多数据会影响它的性能。
结合种种原因,选择了sessionStorage。
在api目录下,axios.js用来处理ajax请求,在axios的请求拦截器中的配置中携带token。
// 请求拦截器
axios.interceptors.request.use((config) => {
// 这个config里面要携带token
config.headers.Authorization = window.sessionStorage.getItem('token') || ''
return config
})
为登录页面配置路由,路由配置在router目录下的index.js文件中配置,并设置路由守卫
router.beforeEach(async (to, from, next) => {
if (to.path !== '/login') {
if (window.sessionStorage.getItem('token')) {
next()
} else {
next('/login')
}
} else {
next()
}
})
当sessionStorage中没有登录的token值时,页面会自动跳转到登录界面。
主界面Home
主界面布局主要分为三大块,Header、Aside和Main,使用了element-ui中的Container布局容器。首先要在router中为Home配置路由并引入。
Header
头部分为左边和右边两部分,左边包含一张系统的logo图片和title文字;右边则是一个退出此平台的按钮,当店家此按钮时,则会清除存储在sessionStorage中的token值,当用户再次进入此Home页面时则会自动跳转到登录页面,必须登录之后才可以进入。
Aside
Aside里放的是侧边导航栏,使用NavMenu导航菜单,根据后台侧边导航接口,异步请求导航内容。
// 请求侧边导航栏数据
async created() {
const { data: res } = await this.$http('menus')
this.menuList = res.data
},
因为每一个一级导航都有一个相对应的icon图标,因此针对图标定义了一个icon图标数组,专门用来存放一级导航对应的图标,最后再遍历循环。
async getMenuList() {
const { data: res } = await this.$http.get('menus')
if (res.meta.status === 200) {
this.menuList = res.data
res.data.forEach(item => {
for (var j in this.iconlist) {
if (item.id + '' === j) {
item.icon = this.iconlist[j]
}
}
});
} else
this.$message.error(res.meta.msg)
}
}
Main
用户列表
在components目录下创建一个新目录,专门用来存放有关用户管理的一些组件。
为用户列表界面配置路由,而这些子界面的路由都作为Home的children路由来配置,配置之后再引入组件即可完成。
用户列表的头部是一个Breadcrumb面包屑导航,因为后面的开发会复用面包屑导航,这里我们将面包屑导航作为一个组件引入,方便后期的复用。
面包屑导航下方是一个Card卡片,卡片中的内容分,为上下两部分,上方是一个复合型的搜索框和一个可以添加新用户的按钮,下方是一个Form表单和Pagination分页,表单中的数据和分页我们通过后台提供的接口来获得。
在操作中有三个按钮,包括编辑、删除和可以为用户分配不同的角色的按钮。
为了方便后期维护,我将编辑用户和分配角色作为子组件引入。
在添加用户中,当点击“添加用户”按钮时,弹出一个添加用户的dilog,包括用户名、密码、邮箱和手机号。当用户添加完成后需要对用户天际的数据验证是否合法,当验证通过点击确定之后,即可向后台发出请求将新添加的数据存储到数据库中。
对于邮箱和手机号需要使用正则表达式来验证其是否合法。
// 验证邮箱是否合法
var checkemail = (rule, value, callback) => {
const regEmail = /^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/;
if (regEmail.test(value)) {
callback()
} else {
callback(new Error('请输入正确的邮箱'))
}
};
// 验证手机号是否合法
var checkmobile = (rule, value, callback) => {
const regMobile = /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/;
if (regMobile.test(value)) {
callback()
} else {
callback(new Error('请输入正确的手机号'))
}
};
在编辑用户中,要实现这样一个功能,当点击某一个用户的编辑按钮时,要弹出一个编辑用户的Dialog对话框,同时此用户的用户名、邮箱和手机号也将同时显示在对话框中的表单中。当用户没有修改信息时,给用户一个提信息;当用户确认已经重新修改信息时,要对后台发出一个请求,将此用户的信息保存起来,同时更新列表中的数据。
要实现以上功能,父子组件之间需要通信,当点击某一个用户时,父组件要“告诉子组件我点击的是哪一个用户,这个用户的用户名等信息是什么”,而子组件通过prop
来接收来自父组件的数据,当用户修改完成后子组件通过$emit
抛出一个事件,“告诉我已经修改完成了,你可以更新列表数据了”。
在分配角色中,用到了Select选择器器,需要先获取到所有的角色列表,根据其唯一的id值来确认选择的是哪一个角色。
权限管理
角色列表
在角色列表中,不同的用户有不同的权限等级,不同的等级有不同的tag颜色,使用v-if、v-else
即可实现此功能。
权限列表
在权限列表中,当点击分配权限按钮时,在弹出的对话框中是一个权限树,可以给用户分配不同的权限。
商品管理
商品列表
在商品列表中除了正常请求商品的数据之外,还有一个添加按钮。当我们点击添加按钮时需要跳转到另一个页面,因此需要为商品添加按钮配置路由,这个路由也是在Home中注册,然后给添加按钮增加一个点击事件
@click="$router.push('/goods/add')"
,即可实现跳转。
添加商品上方有一个Steps步骤条,下方左侧是一个左边的Tabs标签页。
左侧tabs标签页中的商品内容中需要使用到富文本编辑器,现在项目管理器中下载,然后在main.js中引入,最后直接使用即可。
//main.js
// 引入富文本编辑器
import VueQuillEditor from 'vue-quill-editor'
// 引入富文本编辑器的 styles
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
// 全局注册富文本编辑器
Vue.use(VueQuillEditor)
//在页面中的使用
<quill-editor v-model="addGoodsForm.goods_introduce"></quill-editor>
分类参数
分类参数上方是一个Cascader级联选择器,下方是一个Table表格
商品分类
在商品分类中的Form表单中用到了tree-table表格树。
在项目管理器中可以搜索vue-table-with-tree-grid
并将其安装到项目中,也可以使用
npm install vue-table-with-tree-grid -S
安装,安装之后main.js文件中引用并注册即可使用。
// 引入表格树
import TreeTable from 'vue-table-with-tree-grid'
// 全局注册组件
Vue.component('tree-table', TreeTable)
订单管理
订单列表
订单列表的数据请求同用户列表的数据请求,无甚大区别。
数据统计
数据统计是一个echarts图,也是用到了lodash,因此我们需要先下载,使用
npm install echarts -S
npm install lodash -S
或者在项目管理器中搜索下载也可。
下载之后在需要使用的页面中引入即可使用。
// 1、引入 echarts.js
import * as echarts from 'echarts';
// 引入loadsh
import _ from 'lodash'
具体实例代码如下:
<template>
<el-card>
<div id="main" style="width: 750px;height:450px;"></div>
</el-card>
</template>
<script>
// 1、引入 echarts.js
import * as echarts from 'echarts';
// 引入loadsh
import _ from 'lodash'
export default {
data() {
return {
// 需要合并的数据
options: {
title: {
text: '用户来源'
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#E9EEF3'
}
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: [
{
boundaryGap: false
}
],
yAxis: [
{
type: 'value'
}
]
}
}
},
// 此时页面已经渲染完毕
async mounted() {
// 2、 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));
const { data: res } = await this.$http.get('reports/type/1')
if (res.meta.status !== 200) {
return this.$message.error('请求折线图数据失败')
}
// 3、指定图表的配置项和数据
const result = _.merge(res.data, this.options)
// 4、 使用刚指定的配置项和数据显示图表。
myChart.setOption(result);
// console.log(option);
}
};
</script>