vue项目-day02
1-项目基础文件
1.1-element封装
/utils/element.js
// 全部导入
import Vue from 'vue';
import element from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
// 注册
Vue.use(element);
// 封装一个成功提示
Vue.prototype.$success=function(message){
this.$message({
type:'success',
message
});
}
// 封装一个失败提示
Vue.prototype.$error=function(message){
this.$message({
type:'error',
message
});
}
// 确认提示框
Vue.prototype.$myConfirm=function(callback){
this.$confirm('确认删除?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// 确认之后的逻辑操作
callback&&callback();
}).catch(() => {
// 取消之后的逻辑操作
});
}
1.2-路由模块
/router/index.js
import Vue from 'vue';
import Router from 'vue-router';
const Login=()=>import('../pages/Login');
const Layout=()=>import('../pages/Layout');
// 菜单管理
const Menu=()=>import('../pages/menu/Index');
// 角色管理
const Role=()=>import('../pages/role/Index');
// 管理员管理
const Admin=()=>import('../pages/admin/Index');
Vue.use(Router);
// 定义路由规则
const routes= [
{
path: '/login',
name: 'Login',
component: Login,
meta:{
title:'管理员登录'
}
},
{
path:'/',
component:Layout,
meta:{
title:'小U商城后台管理系统'
},
children:[
{
path:'/menu',
component:Menu,
meta:{
title:'菜单管理'
}
},
{
path:'/role',
component:Role,
meta:{
title:'角色管理'
}
},
{
path:'/admin',
component:Admin,
meta:{
title:'管理员管理'
}
}
]
}
];
const router=new Router({
routes
});
// 路由导航守卫
router.beforeEach(function(to,from,next){
// 如果用户访问的是非登录页面
if(to.path!=='/login'){
// 读取本地存储
const loginInfo=JSON.parse(localStorage.getItem('loginInfo')||'{}');
// 如果没有登录凭证
if(!loginInfo.token){
return next('/login');
}
}
next();
// 动态设置页面标题
document.title=to.meta.title;
});
export default router;
1.3-事件中心vm
utils/vm.js
// 导入vue
import Vue from 'vue';
// 创建一个空vue实例
const vm=new Vue();
// 导出
export default vm;
2-菜单管理
2.1-菜单添加&编辑
pages/menu/Modal.vue
<template>
<el-dialog @close="resetForm" :title="formData.id>0?'编辑':'新增'" :visible.sync="info.isShow">
<el-form ref="menuForm" :model="formData" :rules="rules" label-width="60px">
<el-form-item label="类型" prop="type">
<el-radio-group v-model="formData.type">
<el-radio :label="1">目录</el-radio>
<el-radio :label="2">菜单</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="上级" v-if="formData.type===2" prop="pid">
<el-select placeholder="请选择" v-model="formData.pid">
<el-option :value="0" label="顶级菜单"></el-option>
<el-option
v-for="item in menuList"
:key="item.id"
:label="item.title"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="名称" prop="title">
<el-input placeholder="菜单标题" v-model="formData.title"></el-input>
</el-form-item>
<el-form-item label="图标" v-if="formData.type===1" prop="icon">
<el-input placeholder="图标" v-model="formData.icon"></el-input>
</el-form-item>
<el-form-item label="地址" v-if="formData.type===2" prop="url">
<el-input placeholder="地址" v-model="formData.url"></el-input>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio :label="1">正常</el-radio>
<el-radio :label="2">禁用</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="info.isShow = false">取 消</el-button>
<el-button type="primary" @click="submit">确 定</el-button>
</div>
</el-dialog>
</template>
<script>
import { mapState } from 'vuex';
export default {
computed:{
...mapState({menuList:state=>state.menu.menuList})
},
// 接收父组件传递过来的数据
props: ['info'],
data() {
return {
// 和表单元素进行绑定
formData: {
id:0,
pid:0,
title:'',
icon:'',
status:'',
type:1,
url:''
},
// 表单校验规则
rules:{
title:{required:true,message:'请输入名称',trigger:'blur'},
status:{required:true,message:'请选择状态',trigger:'blur'}
}
};
},
methods:{
// 表单提交
submit(){
this.$refs.menuForm.validate(valid=>{
if(valid){
const url=this.formData.id>0?'/menuedit':'/menuadd';
// 提交表单
this.$http.post(url,this.formData).then(res=>{
if(res.code===200){
this.$success(res.msg);
// 1-关闭对话框组件
this.info.isShow=false;
// 2-更新数据列表
this.$emit('updateList')
}else{
this.$error(res.msg);
}
})
}
});
},
// 更新formData
setFormData(obj){
this.formData={...obj}
},
resetForm(){
// 重置表单
this.$refs.menuForm.resetFields();
this.formData={
pid:0,
title:'',
icon:'',
status:'',
type:1,
url:''
}
}
}
};
</script>
<style>
</style>
2.2-菜单删除
pages/menu/Index.vue
<el-table-column label="操作">
<template v-slot="props">
<el-button @click="del(props.row.id)" circle size="mini" icon="el-icon-delete" type="danger"></el-button>
</template>
</el-table-column>
export default {
methods:{
del(id){
this.$myConfirm(()=>{
// 发请求删除据
this.$http.post('/menudelete',{id}).then(res=>{
if(res.code===200){
this.$success(res.msg);
// 更新数据列表
this.getMenuListAction();
return false;
}
this.$error(res.msg);
})
});
}
}
3-角色管理
3.0-数据层封装
/request/role.js
import axios from '../utils/http';
// 获取菜单列表
export async function getMenuList(){
const res=await axios.get('/menulist?istree=1');
if(res.code===200){
return res.list;
}
return false;
}
/store/modules/role.js
// 导入数据请求方法
import { getRoleList } from '../../request/role'
export default {
// 开启独立命名空间
namespaced:true,
state(){
return {
// 角色列表
roleList:[]
}
},
mutations:{
// 初始化角色列表
// state: 系统自动注入的参数
// list:额外参数(是异步action通过数据接口获取的角色列表)
roleListInit(state,list){
state.roleList=list;
}
},
actions:{
getRoleListAction({commit}){
getRoleList().then(res=>{
if(res){
// 通过commit调用roleListInit
commit('roleListInit',res);
}
})
}
}
}
/store/index.js
// 1-导入
import Vue from 'vue';
import Vuex from 'vuex';
// 2-注册
Vue.use(Vuex);
// 导入子模块
import menu from './modules/menu';
import role from './modules/role';
import admin from './modules/admin'
// 3-创建数据存储对象
const store=new Vuex.Store({
state:{},
mutations:{},
getter:{},
actions:{},
modules:{
menu,
role,
admin
}
});
// 4-导出
export default store;
3.1-角色列表
pages/role/Inde.vue
<template>
<el-card>
<el-button
@click="info.isShow=!info.isShow"
type="primary"
icon="el-icon-circle-plus-outline"
>新增</el-button>
<el-divider />
<!-- 调用列表组件List -->
<List :roleList="roleList" @updateList="updateList"/>
<!-- 调用表单组件Modal -->
<Modal :info="info" @updateList="updateList" />
</el-card>
</template>
<script>
// 导入子组件
import Modal from "./Modal";
import List from "./List";
import { mapState, mapActions } from "vuex";
export default {
components: {
Modal,
List
},
computed: {
...mapState({
roleList: state => state.role.roleList
})
},
methods: {
...mapActions("role", ["getRoleListAction"]),
// 自定义事件updateList的处理函数
updateList() {
// 更新数据列表
this.getRoleListAction();
}
},
created() {
this.getRoleListAction();
},
data() {
return {
info: {
// 控制对话框的显示状态
isShow: false
}
};
}
};
</script>
pages/role/List.vue
<template>
<el-table :data="roleList" style="width: 100%">
<el-table-column prop="id" label="id" min-width="80"></el-table-column>
<el-table-column prop="rolename" label="角色名称" min-width="180"></el-table-column>
<el-table-column prop="status" label="状态" min-width="180">
<template v-slot="props">
<el-tag type="success" v-if="props.row.status===1">正常</el-tag>
<el-tag type="danger" v-else>禁用</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" min-width="180">
<template v-slot="props">
<el-button @click="edit(props.row)" size="mini" circle icon="el-icon-edit" type="success"></el-button>
<el-button
@click="del(props.row.id)"
size="mini"
circle
icon="el-icon-delete"
type="danger"
></el-button>
</template>
</el-table-column>
</el-table>
</template>
<script>
// 导入事件中心
import vm from "../../utils/vm";
export default {
props: ["roleList"],
methods: {
del(id) {
this.$myConfirm(()=>{
// 1-发送数据请求
this.$http.post('/roledelete',{id}).then(res=>{
if(res.code===200){
this.$success(res.msg);
// 2-更新数据列表
this.$emit('updateList');
}else{
this.$error(res.msg);
}
})
})
},
// 角色编辑
edit(obj) {
// 通过vm.$emit()将待编辑的数据对象传递给Modal
vm.$emit("sendData", { ...obj });
}
}
};
</script>
3.2-角色添加&编辑
pages/role/Modal.vue
<template>
<el-dialog @close="reset" :title="formData.id>0?'编辑':'新增'" :visible.sync="info.isShow">
<el-form label-width="80px" :model="formData" :rules="rules" ref="formRef">
<el-form-item label="角色名称" prop="rolename">
<el-input placeholder="角色名称" v-model="formData.rolename"></el-input>
</el-form-item>
<el-form-item label="角色权限" prop="menus">
<el-tree
ref="treeRef"
:data="menuList"
show-checkbox
node-key="id"
default-expand-all
:props="defaultProps"
></el-tree>
</el-form-item>
<el-form-item label="角色状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio :label="1">正常</el-radio>
<el-radio :label="2">禁用</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="reset">取 消</el-button>
<el-button type="primary" @click="submit">确 定</el-button>
</div>
</el-dialog>
</template>
<script>
// 导入事件中心
import vm from '../../utils/vm'
import { mapState, mapActions } from "vuex";
export default {
props: ["info"],
created() {
// 初始化数据menuList
this.getMenuListAction();
// 监听自定义事件
vm.$on('sendData',(obj)=>{
// 1-更新this.formData
this.formData=obj;
// 2-显示对话框组件
this.info.isShow=true;
// 3-勾选当前角色操作权限
setTimeout(() => {
this.$refs.treeRef.setCheckedKeys(this.formData.menus.split(','));
}, 100);
})
},
computed: {
...mapState({
menuList: state => state.menu.menuList
})
},
methods: {
...mapActions("menu", ["getMenuListAction"]),
// 表单提交
submit() {
// 终极的表单校验
this.$refs.formRef.validate(valid => {
if (valid) {
// 1-获取用户勾选的节点
const keys=this.$refs.treeRef.getCheckedKeys().join(',');
// 2-手动更新formData.menus
this.formData.menus=keys;
// 3-提交数据
const url=this.formData.id>0?'/roleedit':'/roleadd'
this.$http.post(url,this.formData).then(res=>{
if(res.code===200){
this.$success(res.msg);
// 通过自定义事件通知父组件更新数据列表
this.$emit('updateList');
// 重置数据
this.reset();
return false;
}
this.$error(res.msg);
});
}
});
},
// 数据重置
reset(){
// 1-重置表单
this.formData= {
rolename: "", // 角色名称
status: "", // 角色状态
menus: "" // 角色权限
}
// 清空树形组件的勾选项
this.$refs.treeRef.setCheckedKeys([]);
// 2-关闭对话框
this.info.isShow=false;
}
},
data() {
// 自定义表单校验规则方法
var validMenus = (rule, value, callback) => {
const keys = this.$refs.treeRef.getCheckedKeys();
if (keys.length <= 0) {
return callback(new Error("请选择操作权限"));
}
// 表示表单校验通过
callback();
};
return {
isShow: true,
// 属性控件的相关属性值
defaultProps: {
children: "children",
label: "title"
},
// 和表单元素进行双向数据绑定
formData: {
id:0,
rolename: "", // 角色名称
status: "", // 角色状态
menus: "" // 角色权限
},
// 表单校验规则
rules: {
rolename: {
required: true,
message: "请输入角色名称",
trigger: "blur"
},
status: { required: true, message: "请选择状态", trigger: "blur" },
// 自定义表单校验
menus:{validator:validMenus,trigger:'blur'}
}
};
}
};
</script>
3.3-角色删除
pages/role/List.vue
<el-table-column label="操作" min-width="180">
<template v-slot="props">
<el-button
@click="del(props.row.id)"
size="mini"
circle
icon="el-icon-delete"
type="danger"
>
</el-button>
</template>
</el-table-column>
export default {
methods: {
del(id) {
this.$myConfirm(()=>{
// 1-发送数据请求
this.$http.post('/roledelete',{id}).then(res=>{
if(res.code===200){
this.$success(res.msg);
// 2-更新数据列表
this.$emit('updateList');
}else{
this.$error(res.msg);
}
})
})
}
}
}
4-管理员管理
4.0-数据层封装
/request/admin.js
// 导入axios
import axios from '../utils/http';
// 获取管理员列表
// params={page:'页码',size:'每页显示数据条数'}
export async function getAdminList(params){
const res=await axios.get('/userlist',{
params
});
if(res.code===200){
return res.list;
}
return false;
}
// 获取数据总条数
export async function getAdminTotal(){
const res=await axios.get('/usercount');
if(res.code===200){
return res.list[0].total;
}
return false;
}
/store/modules/admin.js
// 导入数据请求方法
import { getAdminList,getAdminTotal } from '../../request/admin';
export default {
// 开启独立命名空间
namespaced:true,
state(){
return {
// 管理员列表
adminList:[],
// 管理员总数
adminTotal:0,
}
},
mutations:{
// 初始化adminList
adminListInit(state,list){
state.adminList=list;
},
// 初始化adminTotal
adminTotalInit(state,total){
state.adminTotal=total;
}
},
actions:{
// parmas={page:'页码',size:'每页显示的数据条数'}
getAdminListAction({commit},parmas){
getAdminList(parmas).then(list=>{
// 通过commit方法调用同步mutation方法adminListInit实现更新数据
if(list){
commit('adminListInit',list);
}
});
},
getAdminTotalAction({commit}){
getAdminTotal().then(total=>{
// 通过commit方法调用同步mutation方法adminListInit实现更新数据
if(total){
commit('adminTotalInit',total);
}
});
},
}
}
4.1-管理员列表
pages/admin/Index.vue
<template>
<el-card>
<el-button @click="info.isShow=!info.isShow" icon="el-icon-circle-plus-outline" type="primary">新增</el-button>
<el-divider />
<!-- 通过自定义属性, 向子组件传递数据 -->
<!-- 列表组件 -->
<List @updatePage="updatePage" :size="size" :adminList="adminList" :adminTotal="adminTotal" />
<!-- 表单组件 -->
<Modal @updateList="updateList" :info="info"/>
</el-card>
</template>
<script>
// 导入vuex的辅助方法
import { mapState, mapActions } from "vuex";
// 导入列表组件
import List from "./List";
import Modal from "./Modal";
export default {
data() {
return {
info: {
// 控制对话框组件的显示状态
isShow: false
},
// 页码
page: 1,
// 每页显示的数据条数
size: 2
};
},
computed: {
...mapState({
adminList: state => state.admin.adminList,
adminTotal: state => state.admin.adminTotal
})
},
methods: {
...mapActions("admin", ["getAdminListAction", "getAdminTotalAction"]),
// 自定义事件updatePage处理函数
updatePage(page) {
// 1-更新页码
this.page = page;
// 2-重新请求数据列表
this.getAdminListAction({ page: this.page, size: this.size });
},
// 自定义事件updateList的处理方法
updateList(){
// 更新数据列表
this.getAdminListAction({page:this.page,size:this.size});
// 更新数据总条数
this.getAdminTotalAction();
}
},
components: { List, Modal },
created() {
this.getAdminListAction({ page: this.page, size: this.size });
this.getAdminTotalAction();
}
};
</script>
/pages/admin/List.vue
<template>
<div>
<el-table :data="adminList" style="width: 100%">
<el-table-column prop="id" label="id" min-width="80"></el-table-column>
<el-table-column prop="rolename" label="角色" min-width="180"></el-table-column>
<el-table-column prop="username" label="账号" min-width="180"></el-table-column>
<el-table-column prop="status" label="状态" min-width="180">
<template v-slot="props">
<el-tag type="success" v-if="props.row.status===1">正常</el-tag>
<el-tag type="danger" v-else>禁用</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" min-width="180">
<template>
<el-button size="mini" circle type="success" icon="el-icon-edit"></el-button>
<el-button size="mini" circle type="danger" icon="el-icon-delete"></el-button>
</template>
</el-table-column>
</el-table>
<!--
total:数据总条数
page-size: 每页显示的数据条数
current-change: 分页按钮点击事件
-->
<el-pagination @current-change="pageUpdate" :page-size="size" background layout="prev, pager, next" :total="adminTotal"></el-pagination>
</div>
</template>
<script>
export default {
props:['adminTotal','adminList','size'],
data() {
return {}
},
methods:{
// 分页按钮被点击的处理函数
// page: 分页按钮的页码, 系统自动注入
pageUpdate(page){
// 通过this.$emit()将最新页码值传递给父组件Index
this.$emit('updatePage',page);
}
}
};
</script>
4.2-管理员添加
pages/admin/Modal.vue
<template>
<el-dialog @close="reset" title="新增" :visible.sync="info.isShow">
<el-form ref="formRef" label-width="80px" :model="formData" :rules="rules">
<el-form-item label="角色" prop="roleid">
<el-select v-model="formData.roleid">
<el-option
v-for="item in roleList"
:key="item.id"
:label="item.rolename"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="账号" prop="username">
<el-input placeholder="账号" v-model="formData.username"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input placeholder="密码" v-model="formData.password" type="password"></el-input>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio :label="1">正常</el-radio>
<el-radio :label="2">禁用</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button>取 消</el-button>
<el-button type="primary" @click="submit">确 定</el-button>
</div>
</el-dialog>
</template>
<script>
// 导入辅助方法
import { mapState, mapActions } from "vuex";
export default {
computed: {
...mapState({
roleList: state => state.role.roleList
})
},
props: ["info"],
data() {
return {
// 表单数据模型
formData: {
// 角色id
roleid: '',
// 账号
username: "",
// 密码
password: "",
// 状态
status: ""
},
// 表单校验规则对象
rules: {
roleid: { required: true, message: "请选择角色", trigger: "blur" },
username: { required: true, message: "请输入账号", trigger: "blur" },
password: { required: true, message: "请输入密码", trigger: "blur" },
status: { required: true, message: "请选择状态", trigger: "blur" }
}
};
},
methods: {
...mapActions("role", ["getRoleListAction"]),
submit(){
this.$refs.formRef.validate(valid=>{
if(valid){
// 发请求
this.$http.post('/useradd',this.formData).then(res=>{
if(res.code===200){
this.$success(res.msg);
// 更新数据列表: 通知父组件更新数据列表
this.$emit('updateList');
// 重置信息
this.reset();
}else{
this.$error(res.msg);
}
})
}
});
},
// 数据重置
reset(){
this.formData={
// 角色id
roleid: '',
// 账号
username: "",
// 密码
password: "",
// 状态
status: ""
}
// 隐藏对话框组件
this.info.isShow=false;
}
},
created() {
this.getRoleListAction();
}
};
</script>