从0开始搭建vue + flask 旅游景点数据分析系统( 五):【用户管理页面、 景点管理页面、个人设置页面编写】

avatar
作者
猴君
阅读量: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   }, 

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!