Vue + ElementUI 制作后台管理类项目

历时2周左右,我终于完成了我的毕业项目。虽说页面不是特别美观,但是对于一个后端开发人员来说,我觉得已经是很不错了。今天主要分享前端页面的实现,以及如何对接后端的接口,先看项目效果。

目录

一、页面展示

登录界面

管理界面

数据操作

二、代码展示

登录页代码

管理页代码

操作页代码 

三、重点突破

路由突破

接口突破

四、总结 

一、页面展示

登录界面

管理界面

数据操作

二、代码展示

登录页代码

<template>
  <div class="login_page">
    <div class="logo">
      <div class="txt">九江</div>
      <img class="img" src="../assets/logo.jpg" alt="">
      <div class="txt">科技</div>
    </div>
    <div class="login-container">
      <h3>自动化测试管理平台</h3>
      <el-form label-width="100px" v-model="login">
        <el-form-item label="用户名">
          <el-input v-model="login.phone" clearable placeholder="输入不少于三位的字母和数字"></el-input>
        </el-form-item>
        <el-form-item label="口令">
          <el-input v-model="login.pwd" show-password clearable placeholder="输入不少于六位的字母和数字"></el-input>
        </el-form-item>
        <el-form-item class="form_foot">
            <el-checkbox label="是否记住" v-model="remember" style="margin-right:25px"></el-checkbox>
            <el-button type="primary" size="medium" native-type="button" @click="loginHandler" style="background: #191970;border: none">登录</el-button>
            <el-button type="danger" size="medium" native-type="button" @click="cover" style="border: none">重置</el-button>
        </el-form-item>
      </el-form>
    </div>
  </div>
</template>

<script>
export default {
  phone: 'Login',
  data () {
    return {
      login: {
        phone: '',
        pwd: ''
      },
      remember: false
    }
  },
  methods: {
    loginHandler () {
      console.info(this.login, this.remember)
      if (!/\w{3,}/.test(this.login.phone)) {
        this.$message({
          message: '用户名不能为空或者不合法',
          type: Error
        })
        return false
      }
      if (!/\w{6,}/.test(this.login.pwd)) {
        this.$message({
          message: '口令不能为空或者不合法',
          type: Error
        })
        return false
      }
      this.$http.post('/user/login/', this.login).then(resp => {
        if (resp.status === 200) {
          const { token, data } = resp.data
          sessionStorage.setItem('token', token)
          // data=>{nick_name, phone, addr, sex}
          sessionStorage.setItem('user', JSON.stringify(data))
          this.$router.push('/')
        } else {
          this.$message.error(resp.data.msg)
        }
      })
    },
    cover () {
      this.login.phone = ''
      this.login.pwd = ''
    }
  }
}
</script>

<style scoped>
  .login_page {
    height: 100%;
    width: 100%;
    background-image:url(../assets/6.jpg);
    background-size: cover;
  }
  .logo{
    display: flex;
    /* width: 100px; */
    height: 100px;
    position: relative;
    top: 28%;
    border-radius: 50%;
    justify-content: center;
  }
  .txt{
    /* width: 100px; */
    height: 100px;
    line-height: 100px;
    font-size: 50px;
    background: #EEE url(data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAIAAAAmkwkpAAAAHklEQVQImWNkYGBgYGD4//8/A5wF5SBYyAr+//8PAPOCFO0Q2zq7AAAAAElFTkSuQmCC) repeat;
    text-shadow: 5px -5px #00008B, 4px -4px black;
    font-weight: bold;
    -webkit-text-fill-color: transparent;
    -webkit-background-clip: text;
  }
  .img{
    width: 100px;
    height: 100px;
    border-radius: 50%;
    margin: 0 20px;
  }
  .login-container {
    width: 400px;
    height: 280px;
    border: 1px solid #fff;
    position: relative;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    border-radius: 20px 20px 0 0;
    overflow: hidden;
  }
  .login-container h3 {
    margin: 0;
    padding: 15px;
    background-color:#00688B;
    color: white;
    text-align: center;
  }
  .el-row {
    padding: 10px;
  }
  .title {
    text-align: left;
    padding-left: 20px;
  }
  .el-form{
    padding: 20px;
  }
  .el-form .el-button{
    /* position: absolute; */
    /* right: 5px; */
  }
  /* .form_foot{
    display: flex;
    justify-content: space-between;
  } */
  .form_button{
    display: flex;
    justify-content: flex-end;
  }
</style>

管理页代码

<template>
  <div>
    <breadcrumb title="用户中心"></breadcrumb>
    <div class="search-container">
        <el-button type="primary" slot="append" @click="loadsugs()">用户信息</el-button>
    </div>
    <el-table :data="datas" border stripe height="380px">
      <el-table-column prop="id" label="序号" width="120px" align="center"></el-table-column>
      <el-table-column prop="phone" label="手机号" width="140px" align="center"></el-table-column>
      <el-table-column prop="name" label="姓名" width="160px" align="center"></el-table-column>
      <el-table-column prop="sex" label="性别" width="100px" align="center"></el-table-column>
      <el-table-column prop="age" label="年龄" width="100px" align="center"></el-table-column>
      <el-table-column prop="role" label="角色" width="100px" align="center"></el-table-column>
      <el-table-column prop="email" label="邮箱" width="320px" align="center"></el-table-column>
      <el-table-column prop="header" label="头像" width="180px" align="center">
        <template slot-scope="scope">
          <img style="width:30px;height:30px;border-radius:50%;" :src="'http://127.0.0.1:8000/m/'+scope.row.header">
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  name: 'AppUser',
  data () {
    return {
      datas: []
    }
  },
  mounted () {
    this.loadsugs()
  },
  methods: {
    tableRowClassName ({ row, rowIndex }) {
      if (rowIndex % 2 === 1) {
        return 'info-row'
      } else if (rowIndex % 2 === 0) {
        return 'success-row'
      }
      return ''
    },
    loadsugs () {
      this.$http.get('/user/get_user_info/').then(resp => {
        this.datas = resp.data
      })
    }
  }
}
</script>

<style>
.el-table {
  width: 100%;
}
.search-container {
  height: 50px;
  display: flex;
  align-items: center;
}
.el-autocomplete {
  width: 500px;
}
.el-table .warning-row {
    background: oldlace;
  }
.el-table .success-row {
    background: #f0f9eb;
  }
</style>

操作页代码 

<template>
  <div>
    <breadcrumb title="用户操作"></breadcrumb>
    <div class="search-container">
       <el-button type="primary" @click="loaddata()">刷新</el-button>
    </div>
    <el-table :data="datas" border stripe height="370px">
      <el-table-column prop="id" label="序号" width="50px" align="center"></el-table-column>
      <el-table-column prop="phone" label="手机号" width="140px" align="center"></el-table-column>
      <el-table-column prop="name" label="姓名" width="120px" align="center"></el-table-column>
      <el-table-column prop="sex" label="性别" width="75px" align="center"></el-table-column>
      <el-table-column prop="age" label="年龄" width="75px" align="center"></el-table-column>
      <el-table-column prop="role" label="角色" width="160px" align="center"></el-table-column>
      <el-table-column prop="email" label="邮箱" width="280px" align="center"></el-table-column>
      <el-table-column prop="is_active" label="状态" width="120px" align="center"></el-table-column>
      <el-table-column label="操作" width="220px" align="center">
        <template slot-scope="scope">
          <el-button type="primary" icon="el-icon-edit" circle size="mini" title="编辑" @click="edit(scope.row)"></el-button>
          <el-button type="danger" icon="el-icon-delete" circle size="mini" title="注销"  @click="del(scope.row)"></el-button>
          <el-button type="success" icon="el-icon-refresh-left" circle size="mini" title="恢复"  @click="relive(scope.row)"></el-button>
        </template>
      </el-table-column>
    </el-table>
    <el-dialog title="编辑用户信息" :visible.sync="dialogVisible">
     <el-tabs>
       <el-tab-pane label="用户信息">
         <el-form v-model="editUser">
           <el-form-item label="姓名">
             <el-input v-model="editUser.name"></el-input>
           </el-form-item>
           <el-form-item label="性别">
             <el-input v-model="editUser.sex"></el-input>
           </el-form-item>
           <el-form-item label="年龄">
             <el-input v-model="editUser.age"></el-input>
           </el-form-item>
           <el-form-item label="邮箱">
             <el-input v-model="editUser.email"></el-input>
           </el-form-item>
<!--          <el-date-picker >
             <el-input v-model="editUser.end_time" ></el-input>
           </el-date-picker> -->
           <!-- <el-date-picker label="结束时间" v-model="editUser.end_time" type="datetime" placeholder="选择日期时间"></el-date-picker> -->
         </el-form>
       </el-tab-pane>
     </el-tabs>
      <div slot="footer" class="dialog-footer">
          <el-button @click="dialogVisible = false">取 消</el-button>
          <el-button type="primary" @click="editCommit">确 定</el-button>
        </div>
    </el-dialog>
  </div>
</template>

<script>
// import fecha from 'fecha'
// import moment from 'moment'
export default {
  name: 'ChangeUser',
  data () {
    return {
      datas: [],
      dialogVisible: false,
      editUser: {
        phone: '',
        info: {
          name: '',
          nick_name: '',
          note: ''
        }
      }
    }
  },
  mounted () {
    this.loaddata()
  },
  methods: {
    loaddata () {
      this.$http.get('/user/get_user_info/').then(resp => {
        this.datas = resp.data
      })
    },
    edit (user) {
      if (!user.info) {
        user.info = { name: '', nick_name: '', note: '' }
      }
      this.editUser = user
      this.dialogVisible = true
    },
    editCommit () {
      this.$http.post('/user/updata_user/' + this.editUser.id + '/', this.editUser).then(resp => {
        if (resp.status === 200) {
          this.$message.success('修改成功')
          this.loaddata()
        } else {
          this.$message.error('修改失败')
        }
      })
      this.dialogVisible = false
    },
    del (row) {
      this.$confirm('确认是否删除').then(() => {
        this.$http.post('/user/del_user/' + row.id + '/', this.editUser).then(resp => {
          if (resp.status === 200) {
            this.$message.success('删除成功')
            this.loaddata()
          } else {
            this.$message.error('此用户已删除')
          }
        }).catch(e => {
          this.$message.error('删除失败, 当前用户存在关联数据。')
        })
      })
    },
    relive (row) {
      this.$confirm('确认恢复').then(() => {
        this.$http.post('/user/relive_user/' + row.id + '/', this.editUser).then(resp => {
          if (resp.status === 200) {
            this.$message.success('恢复成功')
            this.loaddata()
          } else {
            this.$message.error('此用户已恢复')
          }
        }).catch(e => {
          this.$message.error('恢复失败')
        })
      })
    }
  }
}
</script>

<style>
.el-table {
  width: 100%;
}
.search-container {
  height: 50px;
  display: flex;
  align-items: center;
}
.el-autocomplete {
  width: 500px;
}
</style>

 可以看到我们用Vue + elementui其实还是遵循三要素,只不过我们的html变成了template模板,里面用的是elem组件。这块感兴趣的朋友可以查看其他人的博客,如何搭建Vue框架,包括路由配置、模板选择,把整个环境搭建好之后我们可以去element官网学习其使用方法,链接如下:Element - The world's most popular Vue UI framework 详细的讲述了从安装到使用的过程,熟悉其原理和逻辑之后基本上就是面向CV编程。

三、重点突破

作为后端开发人员,当然是更加喜欢研究业务逻辑的。分析接口上的一些原理,页面美不美咱也不知道,咱就是能实现功能就行。页面上存在的增删改查等业务逻辑都需要后台接口,那怎么去开发后台接口呢,可以用java也可以用python,两种语言都有框架,例如java的spring MVC、spring boot,python的django、flask等等。有兴趣的朋友可以下去自学一下。今天主要是前台拿到后台给的接口之后怎么去对接好。

路由突破

首先就是引入路由,路由是在route目录下的index.js文件里面配置的,和这里的name名要一直,目的在于找到当前url所属模块,就是通过路由去定位找到的。其次就是判断前台传入字段,把用的到的字段都放在一个字典里,这里我们经常叫做json数据,因为前后端交互的时候就是通过json数据传递的,前台stingify把json数据转成字符串,后台json.dump,json.load的再把字符串形式的json数据转成字典或列表形式。

接口突破

 

 随后重要的点就是我们的方法,可以理解成函数。一般情况下,前端页面做出一些操作之后,会产生逻辑上的变化的这种,我们会将其设置成点击事件、移动事件、拖拽事件等。这里就以点击事件为例子:

<el-button type="primary" icon="el-icon-edit" circle size="mini" title="编辑" @click="edit(scope.row)"></el-button>
<el-button type="danger" icon="el-icon-delete" circle size="mini" title="注销"  @click="del(scope.row)"></el-button>
<el-button type="success" icon="el-icon-refresh-left" circle size="mini" title="恢复"  @click="relive(scope.row)"></el-button>

可以看到@click后面跟的我们设计好的方法名字,然后再method里面开始对其进行分装,在封装的过程中,需要用到http,或者https网络协议,对网络感兴趣的可以下去研究一下。确定好网络协议、请求方法、请求路径(后台的接口路由)之后我们就可以安装上述代码进行封装了。

随后我们接收后台响应的数据。resp,可以对响应做一些判断、循环等操作。这个可以根据业务需求而定。

四、总结 

总体架构设计就是这样的一个思路,写好一个页面之后其他的都可以举一反三一一列出。设计思路就是:

1、根据需求分析搭建Vue项目框架、模块、路由、配置项、各种插件等

2、设计页面可以参考上述分享的链接进行学习并开发

3、设计样式可以学习一下css的基础知识

4、对接接口:在有接口的前提下,熟悉网络知识、json数据传输知识等

祝愿每一个对计算机感兴趣的朋友都能学有所成。创作不易,记得点赞收藏关注。

  • 5
    点赞
  • 76
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

戒酒的李白-Lisage

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

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

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

打赏作者

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

抵扣说明:

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

余额充值