欢迎体验
Vue3通用后台管理系统
- Vue3.0+ElementPlus+_vue 欢迎页">
当前位置:   article > 正文

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

vue 欢迎页

本项目项目仓库地址: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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

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>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199

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>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 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:{} 
        })
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • Home.vue
<div class="bread">
    <BreadCrumb />
</div>
  • 1
  • 2
  • 3

5.补充知识点

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/355511
推荐阅读
相关标签