电商管理系统
登录功能
表单验证
<el-form ref="loginFormRef"
:model="loginForm"
class="login_form"
label-width="60px"
:rules="loginFormRules">
:rules="loginFormRules"声明一个验证规则
在data中添加如下代码
loginFormRules: {
// 验证用户名是否合法
username: [
{ required: true, message: '请输入登录名称', trigger: 'blur' },
{ min: 3, max: 10, message: '长度在 3 到 5 个字符', trigger: 'blur' }
],
// 验证密码是否合法
password: [
{ required: true, message: '请输入登录密码', trigger: 'blur' },
{ min: 3, max: 10, message: '长度在 3 到 5 个字符', trigger: 'blur' }
]
}
}
重置表单
<el-button @click="resetLoginForm">重置</el-button>
resetLoginForm () {
this.$refs.loginFormRef.resetFields()
this.loginForm.username = ''
this.loginForm.password = ''
},
表单登陆之前预验证
login () {
// 表单登陆之前的的预验证
this.$refs.loginFormRef.validate(async valid => {
if (!valid) return
})
}
当valid为true的时候,表单验证成功,此时则将发起axios请求
登录验证
login () {
// 表单登陆之前的的预验证
this.$refs.loginFormRef.validate(async valid => {
if (!valid) return
const { data: res } = await this.$http.post('login', this.loginForm)
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')
})
}
预验证通过之后,发起请求,将loginForm作为参数通过pos传递到后端,如果返回的状态码不是200,则登陆失败,如果是200,则登陆成功,并且将服务器返回的token值存到sessionStorage中,最后再将路由push到/home
路由导航守卫
为了防止用户未登录就跳转到/home路由,所以需要路由导航守卫,这里主要是在sessionStorage中是否有token值,代码如下
// 挂在路由导航守卫
router.beforeEach((to, from, next) => {
// to将要访问的路径
// from代表从哪一个路径跳转过来
// next()放行或者强制跳转
if (to.path === '/login') return next()
// 获取token
const tokenStr = window.sessionStorage.getItem('token')
if (!tokenStr) return next('/login')
next()
})
主界面
侧边栏数据渲染
// 获取所有菜单
async getMenuList () {
const { data: res } = await this.$http.get('menus')
if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
this.menulist = res.data
},
得到menulist,绑定到html上
<!-- 侧边栏 -->
<el-aside :width="isCollapse ? '64px':'200px' ">
<div class="toggle-btn"
@click="toggleCollapse">{{isCollapseIcon}}</div>
<el-menu background-color="#333744"
text-color="#fff"
active-text-color="#ffd04b"
:unique-opened="true"
:collapse="isCollapse"
:collapse-transition="false"
:router="true"
:default-active="activePath">
<el-submenu v-for="item in menulist"
:key="item.id"
:index="item.id + ''">
<template slot="title">
<i class="el-icon-location"></i>
<span>{{item.authName}}</span>
</template>
<!-- 二级菜单 -->
<el-menu-item :index="'/'+subItem.path"
v-for="subItem in item.children"
:key="subItem.id"
@click="saveNavState('/'+subItem.path)">
<template slot="title">
<i class="el-icon-location"></i>
<span>{{subItem.authName}}</span>
</template>
</el-menu-item>
</el-submenu>
</el-menu>
</el-aside>
index属性就是点击跳转到指定路由上
组件的路由嵌套
index.js
先导入,后配置
{
path: '/home',
name: 'Home',
redirect: '/welcome',
component: Home,
children: [{
path: '/welcome',
name: 'welcome',
component: Welcome
},
{
path: '/users',
component: Users
}]
}
实现的功能就是当跳转到/home的时候,将其重定向为/welcome
注意要在home.vue中添加
用户列表
创建user.vue
先添加面包屑导航,再用卡片 来承载内容
渲染列表
<!-- 用户列表区 -->
<el-table :data="userList"
border
stripe>
<el-table-column type="index"></el-table-column>
<el-table-column label="姓名"
prop="username"></el-table-column>
<el-table-column label="邮箱"
prop="email"></el-table-column>
<el-table-column label="电话"
prop="mobile"></el-table-column>
<el-table-column label="角色"
prop="role_name"></el-table-column>
<el-table-column label="状态"
prop="mg_state">
<template slot-scope="scope">
<el-switch v-model="scope.row.mg_state"
@change="userStateChanged(scope.row)">
</el-switch>
</template>
</el-table-column>
<el-table-column label="操作"
width="180px">
<template>
<el-button type="primary"
icon="el-icon-edit"
size="mini"></el-button>
<el-button type="danger"
icon="el-icon-delete"
size="mini"></el-button>
<el-tooltip effect="dark"
content="分配角色"
placement="top-start"
:enterable="false">
<el-button type="warning"
icon="el-icon-setting"
size="mini"></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
通过插槽即可获取所选行的数据
<template slot-scope="scope">
<el-switch v-model="scope.row.mg_state"
@change="userStateChanged(scope.row)">
</el-switch>
</template>
渲染用户状态
<template slot-scope="scope">
<el-switch v-model="scope.row.mg_state"
@change="userStateChanged(scope.row)">
</el-switch>
</template>
先获取所选行的数据,在将mg_state的boolean值绑定到el-switch元素上。
改变用户状态
@change="userStateChanged(scope.row)"
// 监听用户状态事件
async userStateChanged (status) {
console.log(status)
const { data: res } = await this.$http.put(`users/${status.id}/state/${status.mg_state}`)
if (res.meta.status !== 200) {
status.mg_state = !status.mg_state
return this.$message.error('更新用户状态失败')
}
this.$message.success('更新用户状态数据成功')
},
添加用户
创建自定义对话框
<!-- 添加用户对话框 -->
<el-dialog title="添加用户"
:visible.sync="addDialogVisible"
width="50%"
@close="addDialogClosed">
<!-- 内容主体区 -->
<el-form :model="addForm"
:rules="addFormRules"
ref="addFormRef"
user
label-width="70px">
<el-form-item label="用户名"
prop="username">
<el-input v-model="addForm.username"></el-input>
</el-form-item>
<el-form-item label="密码"
prop="password">
<el-input v-model="addForm.password"></el-input>
</el-form-item>
<el-form-item label="邮箱"
prop="email">
<el-input v-model="addForm.email"></el-input>
</el-form-item>
<el-form-item label="手机"
prop="mobile">
<el-input v-model="addForm.mobile"></el-input>
</el-form-item>
</el-form>
<!-- 底部 -->
<span slot="footer"
class="dialog-footer">
<el-button @click="addDialogVisible = false">取 消</el-button>
<el-button type="primary"
@click="addUser">确 定</el-button>
</span>
</el-dialog>
表单自定义验证规则
在表单el-form中绑定:rules=“addFormRules”
在addFormRules对象里通过validator指定自定义规则
// 表单验证规则对象
addFormRules: {
username: [
{ required: true, message: '请输入用户名称', trigger: 'blur' },
{ min: 3, max: 10, message: '长度在 3 到 10 个字符', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 3, max: 10, message: '长度在 3 到 10 个字符', trigger: 'blur' }
],
email: [
{ required: true, message: '请输入邮箱', trigger: 'blur' },
{ validator: checkEmail, trigger: 'blur' }
],
mobile: [
{ required: true, message: '请输入手机号码', trigger: 'blur' },
{ validator: checkMobile, trigger: 'blur' }
]
}
在return{}之前添加校验规则
// 验证邮箱的校验规则
var checkEmail = (rule, value, cb) => {
const regEmail = /^\w+@[a-z0-9]+\.[a-z]{2,4}$/
if (regEmail.test(value)) {
return cb()
}
cb(new Error('请输入合法的邮箱'))
}
// 验证手机号的校验规则
var checkMobile = (rule, value, cb) => {
const reMobile = /^((13[0-9])|(17[0-1,6-8])|(15[^4,\\D])|(18[0-9]))\d{8}$/
if (reMobile.test(value)) {
return cb()
}
cb(new Error('请输入合法的手机号'))
}
分页设置
在获取所有数据的时候,需要输入pagenum当前页数,pagesize每页的条数,分页控件主要是得到pagenum和pagesize再刷新数据
获取默认的列表
async getUserList () {
const { data: res } = await this.$http.get('users', { params: this.queryInfo })
console.log(res.data)
if (res.meta.status !== 200) {
return this.$message.error('获取用户列表失败')
}
this.userList = res.data.users
this.total = res.data.total
console.log(this.userList)
},
分页控件
<!-- 分页区域 -->
<el-pagination @size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="queryInfo.pagenum"
:page-sizes="[1, 2, 5, 10]"
:page-size="queryInfo.pagesize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
// 监听pagesize改变事件
handleSizeChange (newSize) {
this.queryInfo.pagesize = newSize
this.getUserList()
},
// 监听页码值改变的事件
handleCurrentChange (newPage) {
this.queryInfo.pagenum = newPage
this.getUserList()
},