Vue3+ElementPlus+Koa2 全栈开发后台系统=>欢迎页实现,首页菜单功能实现,菜单交互及递归实现,面包屑实现⑦

本项目项目仓库地址:https://gitee.com/notlaughingzzm/vue3_elementPlus_admin.git

1.欢迎页实现

在这里插入图片描述

<template>
  <div class="welcome">
    <div class="content">
      <div class="sub-title">欢迎体验</div>
      <div class="title">Vue3通用后台管理系统</div>
      <div class="desc">
        - Vue3.0+ElementPlus+Node+Mongo打造通用后台管理系统
      </div>
    </div>
    <div class="img"></div>
  </div>
</template>

<script>
export default {
  name: "welcome",
};
</script>

<style lang="scss">
.welcome {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  background-color: #fff;
  .content {
    position: relative;
    bottom: 40px;
    .sub-title {
      font-size: 30px;
      line-height: 42px;
      color: #333;
    }
    .title {
      font-size: 40px;
      line-height: 62px;
      color: #409eff;
    }
    .desc {
      text-align: right;
      font-size: 14px;
      color: #999;
    }
  }
  .img {
    margin-left: 105px;
    background-image: url("./../assets/images/welcome.png");
    width: 371px;
    height: 438px;
  }
}
</style>

2.首页菜单功能实现

在这里插入图片描述

<template>
	<div class="basic-layout">
		<div :class="['nav', isCollapse ? 'fold' : 'unfold']">
			<!-- 系统logo -->
			<div class="logo">
				<img src='../assets/img/logo-small.png' alt=""/>
				<span>HHS_Admin</span>
			</div>

			<!-- 导航菜单 -->
			<el-menu :default-active="activeMenu" class="nav-menu" background-color="#001529"
			         :router="true" text-color="#fff" :collapse="isCollapse">
				<el-submenu index="1">
					<template #title>
						<i class="el-icon-setting"></i>
						<span>系统管理</span>
					</template>
					<el-menu-item index="1-1">用户管理</el-menu-item>
					<el-menu-item index="1-2">菜单管理</el-menu-item>
				</el-submenu>
				<el-submenu index="2">
					<template #title>
						<i class="el-icon-s-flag"></i>
						<span>审批管理</span>
					</template>
					<el-menu-item index="2-1">休假申请</el-menu-item>
					<el-menu-item index="2-2">待我审核</el-menu-item>
				</el-submenu>
			</el-menu>
		</div>

		<div :class="['content', isCollapse ? 'fold' : 'unfold']">
			<div class="top-crumb">
				<div class="top-crumb-left">
					<div class="fold-menu" @click="toggleNav">
						<i class="el-icon-s-operation"></i>
					</div>
					<div class="bread">
						面包屑
					</div>
				</div>
				<div class="user-info">
					<el-badge :is-dot="true" class="notice" type="danger">
						<i class="el-icon-bell"></i>
					</el-badge>

					<el-dropdown @command="handleCommand">
						<span class="username-span">
              zzm
						</span>
						<template #dropdown>
							<el-dropdown-menu>
									<el-dropdown-item command="user">个人中心</el-dropdown-item>
								<el-dropdown-item command="updatePwd">修改密码</el-dropdown-item>
								<el-dropdown-item command="logout">退出登录</el-dropdown-item>
							</el-dropdown-menu>
						</template>
					</el-dropdown>
				</div>
			</div>
			<div class="wrapper">
				<div class="main">
					<router-view></router-view>
				</div>
			</div>
		</div>
	</div>
</template>

<script>
export default {
	name: "home",
	data() {
		return {
			activeMenu: location.hash.slice(1),
			isCollapse: false,
			menuTree: [],
			userInfo:this.$store.state.userInfo
		}
	},
	mounted() {
	},
	methods: {
		toggleNav() {
			this.isCollapse = !this.isCollapse
		},
		handleCommand(key) {
			if (key === 'updatePwd') {
				this.$message.success('操作成功')
				this.$router.push('/updatePwd')
			} else if (key === 'logout') {
				this.$storage.clearAll()
				this.$store.commit('saveUserInfo','')
				this.userInfo = null
				this.$router.push('/login')
			}else if (key === 'user') {
				this.$router.push('/user')
			}

		},
	}
}
</script>

<style lang="scss" scoped>
.basic-layout {
	position: relative;

	.nav {
		position: fixed;
		width: 200px;
		height: 100vh;
		background-color: #001529;
		color: white;
		overflow-y: auto;
		overflow-x: hidden;
		transition: width 0.3s; // 收缩展开过渡动画

		.logo {
			display: flex;
			align-items: center;
			font-size: 18px;
			height: 50px;

			img {
				margin: 0 16px;
				width: 32px;
				height: 32px;
			}
		}

		.nav-menu {
			height: calc(100vh - 50px);
			border-right: none;
		}

		&.fold {
			width: 64px;
		}
		&.unfold {
			width: 200px;
		}
	}

	.content {
		margin-left: 200px;

		&.fold {
			margin-left: 64px;
		}
		&.unfold {
			margin-left: 200px;
		}

		.top-crumb {
			height: 50px;
			line-height: 50px;
			display: flex;
			justify-content: space-between;
			border-bottom: 1px solid #ddd;
			padding: 0 20px;

			.top-crumb-left {
				display: flex;
				align-items: center;
				.fold-menu {
					cursor: pointer;
				}
				.bread {
					margin-left: 10px;
				}
			}

			.user-info {
				.notice {
					margin-right: 20px;
					line-height: 25px;
				}

				.username-span {
					cursor: pointer;
					color: #4091ff;
				}
			}
		}

		.wrapper {
			background: #eef0f3;
			padding: 20px;
			height: calc(100vh - 50px);
			.main {
				background-color: #fff;
				height: 100%;
			}
		}
	}
}
</style>

3.菜单交互及递归实现

  • home.vue组件开发
<template>
	<div class="basic-layout">
		<div :class="['nav', isCollapse ? 'fold' : 'unfold']">
			<!-- 系统logo -->
			<div class="logo">
				<img src='../assets/img/logo-small.png' alt=""/>
				<span>HHS_Admin</span>
			</div>

			<!-- 导航菜单 -->
			<el-menu 
				:default-active="activeMenu" 
				class="nav-menu"
			 	background-color="#001529"
			  :router="true" 
				text-color="#fff" 
				:collapse="isCollapse">
				<tree-menu :menuTree="menuTree"/>
			</el-menu>
		</div>

		<div :class="['content', isCollapse ? 'fold' : 'unfold']">
			<div class="top-crumb">
				<div class="top-crumb-left">
					<div class="fold-menu" @click="toggleNav">
						<i class="el-icon-s-operation"></i>
					</div>
					<div class="bread">
						面包屑
					</div>
				</div>
				<div class="user-info">
					<el-badge :is-dot="noticeCount > 0 ? true : false" class="notice" type="danger">
						<i class="el-icon-bell"></i>
					</el-badge>

					<el-dropdown @command="handleCommand">
						<span class="username-span">
							{{userInfo.userName}}
						</span>
						<template #dropdown>
							<el-dropdown-menu>
								<el-dropdown-item command="user">个人中心</el-dropdown-item>
								<el-dropdown-item command="email65">邮箱:{{userInfo.userEmail}}</el-dropdown-item>
								<el-dropdown-item command="updatePwd">修改密码</el-dropdown-item>
								<el-dropdown-item command="logout">退出登录</el-dropdown-item>
							</el-dropdown-menu>
						</template>
					</el-dropdown>
				</div>
			</div>
			<div class="wrapper">
				<div class="main">
					<router-view></router-view>
				</div>
			</div>
		</div>
	</div>
</template>

<script>
import TreeMenu from './TreeMenu.vue'
export default {
	name: "home",
	components:{TreeMenu},
	data() {
		return {
			activeMenu: location.hash.slice(1),
			isCollapse: false,
			menuTree: [],
			userInfo:this.$store.state.userInfo,
			noticeCount:0
		}
	},
	mounted() {
		this.getNoticeCount()
		this.getMenuList()
	},
	methods: {
		toggleNav() {
			this.isCollapse = !this.isCollapse
		},
		handleCommand(key) {
			if (key === 'updatePwd') {
				this.$message.success('操作成功')
				this.$router.push('/updatePwd')
			} else if (key === 'logout') {
				this.$storage.clearAll()
				this.$store.commit('saveUserInfo','')
				this.userInfo = null
				this.$router.push('/login')
			}else if (key === 'user') {
				this.$router.push('/user')
			}

		},
		async	getNoticeCount(){
			const res = await this.$api.noticeCount()
			this.noticeCount = res
		},
		async	getMenuList(){
			try {
				const res = await this.$api.getMenuList()
				this.menuTree = res
			} catch (error) {
				console.error(error);
			}
		},
	}
}
</script>

<style lang="scss" scoped>
.basic-layout {
	position: relative;

	.nav {
		position: fixed;
		width: 200px;
		height: 100vh;
		background-color: #001529;
		color: white;
		overflow-y: auto;
		overflow-x: hidden;
		transition: width 0.3s; // 收缩展开过渡动画

		.logo {
			display: flex;
			align-items: center;
			font-size: 18px;
			height: 50px;

			img {
				margin: 0 16px;
				width: 32px;
				height: 32px;
			}
		}

		.nav-menu {
			height: calc(100vh - 50px);
			border-right: none;
		}

		&.fold {
			width: 64px;
		}
		&.unfold {
			width: 200px;
		}
	}

	.content {
		margin-left: 200px;

		&.fold {
			margin-left: 64px;
		}
		&.unfold {
			margin-left: 200px;
		}

		.top-crumb {
			height: 50px;
			line-height: 50px;
			display: flex;
			justify-content: space-between;
			border-bottom: 1px solid #ddd;
			padding: 0 20px;

			.top-crumb-left {
				display: flex;
				align-items: center;
				.fold-menu {
					cursor: pointer;
				}
				.bread {
					margin-left: 10px;
				}
			}

			.user-info {
				.notice {
					margin-right: 20px;
					line-height: 25px;
				}

				.username-span {
					cursor: pointer;
					color: #4091ff;
				}
			}
		}

		.wrapper {
			background: #eef0f3;
			padding: 20px;
			height: calc(100vh - 50px);
			.main {
				background-color: #fff;
				height: 100%;
			}
		}
	}
}
</style>

  • TreeMenu.vue组件开发
<template>
  <template v-for="item in menuTree" :key="item._id">
    <el-submenu v-if="item.children && item.children.length>0 && item.children[0].menuType == 1" :key="item._id" :index="item.path">
			<template #title>
				<i :class="item.icon"></i>
				<span>{{item.menuName}}</span>
			</template>
			<tree-menu :menuTree="item.children"/>
	</el-submenu>
	<el-menu-item v-else-if="item.menuType == 1" :index="item.path" :key="item._id">{{item.menuName}}</el-menu-item>
  </template>
</template>

<script>
export default {
	name:'TreeMenu',
	props:{
		menuTree:{
			type:Array,
			default:()=>[]
		}
	}
}
</script>

<style>

</style>
  • api开发
/**
 * api管理
 */
import request from './../utils/request'
 
export default {
    login(params) {
        return request({
            url: '/users/login',
            method: 'post',
            data:params
        })
    },
    noticeCount(params) {
        return request({
            url: '/leave/count',
            method: 'get',
            data:{}
        })
    },
    getMenuList(){
        return request({
            url: '/menu/list',
            method: 'get',
            data:{} 
        })
    }
}

4.面包屑实现

<template>
  <el-breadcrumb separator-class="el-icon-arrow-right">
    <el-breadcrumb-item v-for="(item, index) in breadList" :key="item.path">
      <router-link to="/welcome" v-if="index == 0">{{
        item.meta.title
      }}</router-link>
      <span v-else>{{ item.meta.title }}</span>
    </el-breadcrumb-item>
  </el-breadcrumb>
</template>
<script>
export default {
  name: "BreadCrumb",
  computed: {
    breadList() {
      return this.$route.matched;
    },
  },
};
</script>
  • Home.vue
<div class="bread">
    <BreadCrumb />
</div>

5.补充知识点

在这里插入图片描述

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不停喝水

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值