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

  • 本期任务是编写数据用户管理页面(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
      },
    
  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

麦麦大数据

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

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

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

打赏作者

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

抵扣说明:

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

余额充值