阅读量:0
- 本期任务是编写数据用户管理页面(Users)。
- 编写数据景点管理页面(Tours)页面。
- 编写数据个人设置页面(Profile)页面。
1 编写用户管理页面
修改Users.vue:
<template> <div class="users-container"> <el-card class="box-card"> <div slot="header" class="header"> <span>用户管理</span> <el-button style="float: right; " type="primary" @click="handleAddUser">添加用户</el-button> </div> <el-table :data="users" style="width: 100%"> <el-table-column prop="id" label="ID" width="50"></el-table-column> <el-table-column prop="name" label="姓名" width="180"></el-table-column> <el-table-column prop="email" label="邮箱"></el-table-column> <el-table-column label="操作" width="180"> <template slot-scope="scope"> <el-button @click="handleEditUser(scope.row)" type="text" size="small">编辑</el-button> <el-button @click="handleDeleteUser(scope.row)" type="text" size="small">删除</el-button> </template> </el-table-column> </el-table> </el-card> <el-dialog title="添加用户" :visible.sync="dialogVisible"> <el-form :model="form"> <el-form-item label="姓名" :label-width="formLabelWidth"> <el-input v-model="form.name"></el-input> </el-form-item> <el-form-item label="邮箱" :label-width="formLabelWidth"> <el-input v-model="form.email"></el-input> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="dialogVisible = false">取消</el-button> <el-button type="primary" @click="handleSaveUser">保存</el-button> </div> </el-dialog> </div> </template> <script> export default { data() { return { users: [ { id: 1, name: '张三', email: 'zhangsan@example.com' }, { id: 2, name: '李四', email: 'lisi@example.com' }, { id: 3, name: '王五', email: 'wangwu@example.com' } ], dialogVisible: false, form: { name: '', email: '' }, formLabelWidth: '80px' }; }, methods: { handleAddUser() { this.dialogVisible = true; this.form = { name: '', email: '' }; }, handleEditUser(user) { this.dialogVisible = true; this.form = { ...user }; }, handleDeleteUser(user) { this.users = this.users.filter(u => u.id !== user.id); }, handleSaveUser() { if (this.form.id) { // Edit existing user const index = this.users.findIndex(u => u.id === this.form.id); if (index !== -1) { this.$set(this.users, index, { ...this.form }); } } else { // Add new user const newUser = { ...this.form, id: this.users.length + 1 }; this.users.push(newUser); } this.dialogVisible = false; } } }; </script> <style scoped> .users-container { padding: 20px; } .header{ display: flex; justify-content: space-between; align-items: center; } </style>
效果:
2 编写景点管理页面
新建Tours.vue:
<template> <div class="tours-container"> <el-card class="box-card"> <div slot="header" class="header"> <span>旅游景点管理</span> <el-button type="primary" @click="handleAddTour">添加景点</el-button> </div> <el-table :data="tours" style="width: 100%"> <el-table-column prop="name" label="景点名称" width="180"></el-table-column> <el-table-column prop="alias" label="别名" width="180"></el-table-column> <el-table-column prop="reviewCount" label="评论数" width="100"></el-table-column> <el-table-column prop="rating" label="评分" width="100"></el-table-column> <el-table-column prop="featuredReview" label="精选评论"></el-table-column> <el-table-column prop="country" label="国家" width="120"></el-table-column> <el-table-column prop="city" label="城市" width="120"></el-table-column> <el-table-column label="操作" width="180"> <template slot-scope="scope"> <el-button @click="handleEditTour(scope.row)" type="text" size="small">编辑</el-button> <el-button @click="handleDeleteTour(scope.row)" type="text" size="small">删除</el-button> </template> </el-table-column> </el-table> </el-card> <el-dialog title="编辑景点" :visible.sync="dialogVisible"> <el-form :model="form"> <el-form-item label="景点名称" :label-width="formLabelWidth"> <el-input v-model="form.name"></el-input> </el-form-item> <el-form-item label="别名" :label-width="formLabelWidth"> <el-input v-model="form.alias"></el-input> </el-form-item> <el-form-item label="评论数" :label-width="formLabelWidth"> <el-input v-model="form.reviewCount" type="number"></el-input> </el-form-item> <el-form-item label="评分" :label-width="formLabelWidth"> <el-input v-model="form.rating" type="number"></el-input> </el-form-item> <el-form-item label="精选评论" :label-width="formLabelWidth"> <el-input v-model="form.featuredReview"></el-input> </el-form-item> <el-form-item label="国家" :label-width="formLabelWidth"> <el-input v-model="form.country"></el-input> </el-form-item> <el-form-item label="城市" :label-width="formLabelWidth"> <el-input v-model="form.city"></el-input> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="dialogVisible = false">取消</el-button> <el-button type="primary" @click="handleSaveTour">保存</el-button> </div> </el-dialog> </div> </template> <script> export default { data() { return { tours: [ { id: 1, name: '东京迪士尼度假区', alias: 'Tokyo Disney Resort', reviewCount: 1500, rating: 4.8, featuredReview: '非常美丽的景点', country: '日本', city: '东京' }, { id: 2, name: '东京塔', alias: 'Tokyo Tower', reviewCount: 2500, rating: 4.9, featuredReview: '历史悠久,气势恢宏', country: '日本', city: '东京' }, { id: 3, name: '三鹰之森吉卜力美术馆', alias: 'Ghibli Museum', reviewCount: 1800, rating: 4.7, featuredReview: '象征自由的地标', country: '日本', city: '东京' } ], dialogVisible: false, form: { name: '', alias: '', reviewCount: 0, rating: 0, featuredReview: '', country: '', city: '' }, formLabelWidth: '100px' }; }, methods: { handleAddTour() { this.dialogVisible = true; this.form = { name: '', alias: '', reviewCount: 0, rating: 0, featuredReview: '', country: '', city: '' }; }, handleEditTour(tour) { this.dialogVisible = true; this.form = { ...tour }; }, handleDeleteTour(tour) { this.tours = this.tours.filter(t => t.id !== tour.id); }, handleSaveTour() { if (this.form.id) { const index = this.tours.findIndex(t => t.id === this.form.id); if (index !== -1) { this.$set(this.tours, index, { ...this.form }); } } else { const newTour = { ...this.form, id: this.tours.length + 1 }; this.tours.push(newTour); } this.dialogVisible = false; } } }; </script> <style scoped> .tours-container { padding: 20px; } .header { display: flex; justify-content: space-between; align-items: center; } .dialog-footer { text-align: right; } </style>
效果:
3 编写个人设置页面
新建Profile.vue:
<template> <div class="profile-settings"> <el-card class="box-card"> <div slot="header" class="clearfix"> <span>个人设置</span> </div> <el-form :model="form" label-width="100px" :rules="rules" ref="profileForm"> <el-form-item label="用户名" prop="username"> <el-input v-model="form.username"></el-input> </el-form-item> <el-form-item label="年龄" prop="age"> <el-input v-model="form.age" type="number"></el-input> </el-form-item> <el-form-item label="职业" prop="profession"> <el-input v-model="form.profession"></el-input> </el-form-item> <el-form-item label="签名" prop="signature"> <el-input type="textarea" v-model="form.signature"></el-input> </el-form-item> <el-form-item label="地址" prop="address"> <el-input v-model="form.address"></el-input> </el-form-item> <el-form-item label="手机" prop="phone"> <el-input v-model="form.phone"></el-input> </el-form-item> <el-form-item label="邮箱" prop="email"> <el-input v-model="form.email"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="onSubmit">保存</el-button> <el-button @click="onReset">重置</el-button> </el-form-item> </el-form> </el-card> </div> </template> <script> export default { data() { return { form: { username: '', age: '', profession: '', signature: '', address: '', phone: '', email: '' }, rules: { username: [ { required: true, message: '请输入用户名', trigger: 'blur' } ], age: [ { required: true, message: '请输入年龄', trigger: 'blur' } ], profession: [ { required: true, message: '请输入职业', trigger: 'blur' } ], phone: [ { required: true, message: '请输入手机号码', trigger: 'blur' }, { pattern: /^1[3456789]\d{9}$/, message: '手机号码格式不正确', trigger: 'blur' } ], email: [ { required: true, message: '请输入邮箱地址', trigger: 'blur' }, { type: 'email', message: '邮箱格式不正确', trigger: 'blur' } ] } }; }, methods: { onSubmit() { this.$refs.profileForm.validate((valid) => { if (valid) { alert('保存成功'); } else { console.log('error submit!!'); return false; } }); }, onReset() { this.$refs.profileForm.resetFields(); } } }; </script> <style scoped> .profile-settings { padding: 20px; } </style>
效果:
4 修改router文件
修改router/index.js ,优化了一下之前的导入方式改为使用箭头函数来动态引入,这样项目消耗的资源更少:
const routes = [ { path: '/', component: Layout, redirect: '/dashboard', children: [ { path: 'dashboard', component:()=> import('@/views/Dashboard'), name: 'Dashboard' }, { path: 'users', component:()=> import('@/views/Users'), name: 'Users' }, { path: 'profile', component:()=> import('@/views/Profile'), name: 'Users' }, { path: 'tours', component:()=> import('@/views/Tours'), name: 'Tours' } // 其他子路由 ] }, // 其他路由 ];
5 修改Layout.vue
由于新增了页面,因此菜单也需要修改
<el-menu-item index="/dashboard" @click="navigateTo('/dashboard')"> <i class="el-icon-s-marketing"></i> 数据驾驶舱</el-menu-item> <el-menu-item index="/tours" @click="navigateTo('/tours')"> <i class="el-icon-s-promotion"></i> 景点管理</el-menu-item> <el-menu-item index="/users" @click="navigateTo('/users')"> <i class="el-icon-s-custom"></i> 用户管理</el-menu-item> <el-menu-item index="/profile" @click="navigateTo('/profile')"> <i class="el-icon-s-tools"></i> 个人设置</el-menu-item>
前端整体效果:
6 美化按钮,自定义按钮的颜色
为了酷炫(帅是一辈子的事),我们修改el-button=primary的配色为黑金色,
在assets/styles下新建global.css:
/* 全局覆盖 Element UI 按钮样式 */ .el-button--primary { background-color: #545c64 !important; /* 黑色背景 */ border-color: #000000 !important; /* 黑色边框 */ color: #ffd04b !important; /* 金色文字 */ } .el-button--primary:hover, .el-button--primary:focus { background-color: #333333 !important; /* 深黑色背景 */ border-color: #333333 !important; /* 深黑色边框 */ color: #ffd04b !important; /* 金色文字 */ }
在main.js中引入上述文件
import './assets/styles/global.css'; // 引入全局样式覆盖文件
修改后的按钮效果:
7 修复BUG
打开对话框可以明显发现页面右侧会有抖动
导致这个问题的原因是页面body样式有一个margin 8px的样式,修改方法也是非常简单,在index.html中修改:
<body style="margin: 0;">
菜单栏边缘有一侧白色的边距,这个是由于我们之前设置container的时候有一个1px 的边框颜色,使用深色的菜单栏背景就能看出来了,所以删掉下面的样式:
.container{ height: 100vh; /*border: 1px solid #eee;*/ }
菜单栏active的问题,我们点击用户管理,然后再刷新页面,发现激活的菜单栏变成数据驾驶舱了,其实就是
activeIndex
这个变量刷新页面后变成初始值了,所以修改方式也非常简单,在页面加载完成后给他赋予当前的路由就可以了:mounted() { console.log('当前路径:', this.$route.path) this.activeIndex = this.$route.path },