vue-element-template实战(四)使用mock数据,新增用户管理界面

实现功能包括:用户列表,搜索,新建和编辑。用户数据:用户名,类型,有效期,备注。

一、从vue-element-admin复制文件:

  vue-admin-template\src\components\Pagination文件夹

  vue-admin-template\src\utils\scroll-to.js

二、使用mock.js模拟api返回数据,新建文件/mock/member.js

import Mock from 'mockjs'

const data = Mock.mock({
  'items|50': [
    {
      id: '@id',
      username: '@name',
      'type|1': ['normal', 'vip', 'admin'],
      timestamp: +Mock.Random.date('T'),
      pageviews: '@integer(300, 5000)'
    }
  ]
})

export default [
  {
    url: '/vue-admin-template/member/list',
    type: 'get',
    response: config => {
      const { type, username, page = 1, limit = 20, sort } = config.query

      let mockList = data.items.filter(item => {
        if (type && item.type !== type) return false
        if (username && item.username.indexOf(username) < 0) return false
        return true
      })

      if (sort === '-id') {
        mockList = mockList.reverse()
      }

      const pageList = mockList.filter(
        (item, index) => index < limit * page && index >= limit * (page - 1)
      )

      return {
        code: 20000,
        data: {
          total: mockList.length,
          items: pageList
        }
      }
    }
  },
  {
    url: '/vue-admin-template/member/detail',
    type: 'get',
    response: config => {
      const { id } = config.query
      for (const memeber of data.items) {
        if (memeber.id === +id) {
          return {
            code: 20000,
            data: memeber
          }
        }
      }
    }
  },
  {
    url: '/vue-admin-template/member/create',
    type: 'post',
    response: _ => {
      return {
        code: 20000,
        data: 'success'
      }
    }
  },
  {
    url: '/vue-admin-template/member/update',
    type: 'post',
    response: _ => {
      return {
        code: 20000,
        data: 'success'
      }
    }
  }
]

三、新建文件/src/api/member.js,放用户操作的相关方法

import request from '@/utils/request'

export function fetchList(params) {
  console.log('api')
  return request({
    url: '/vue-admin-template/member/list',
    method: 'get',
    params: params
  })
}

export function fetchMember(id) {
  return request({
    url: 'vue-admin-template/member/detail',
    method: 'get',
    params: { id }
  })
}

export function createMember(data) {
  return request({
    url: '/vue-admin-template/member/create',
    method: 'post',
    data
  })
}

export function updateMember(data) {
  return request({
    url: '/vue-admin-template/member/update',
    method: 'post',
    data
  })
}

四、新建文件:views/member/index.vue中,渲染用户列表。列表使用elementUI的el-table-column组件。新建和编辑窗口使用el-dialog组件

<template>
  <div class="app-container">
    <div class="filter-container" style="margin-bottom:10px">
      <el-input
        v-model="listQuery.username"
        placeholder="昵称"
        style="width: 200px"
        class="filter-item"
        @keyup.enter.native="handleFilter"
      />
      <el-select
        v-model="listQuery.type"
        placeholder="类型"
        clearable
        class="filter-item"
        style="width: 130px"
      >
        <el-option
          v-for="item in userTypeOptions"
          :key="item.key"
          :label="item.display_name+'('+item.key+')'"
          :value="item.key"
        />
      </el-select>
      <el-button class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">搜索</el-button>
      <el-button
        class="filter-item"
        style="margin-left: 10px"
        type="primary"
        icon="el-icon-edit"
        @click="handleCreate"
      >新建</el-button>
    </div>
    <el-table
      v-loading="listLoading"
      :data="list"
      element-loading-text="Loading"
      border
      fit
      highlight-current-row
    >
      <el-table-column align="center" label="ID" width="95">
        <template slot-scope="scope">{{ scope.$index }}</template>
      </el-table-column>
      <el-table-column label="用户名">
        <template slot-scope="scope">{{ scope.row.username }}</template>
      </el-table-column>
      <el-table-column label="类型" width="110" align="center">
        <template slot-scope="scope"><span>{{ scope.row.type }}</span></template>
      </el-table-column>
      <el-table-column label="Date" width="150px" align="center">
        <template slot-scope="{row}">
          <span>{{ row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" width="230" class-name="small-padding fixed-width">
        <template slot-scope="{ row, $index }">
          <el-button type="primary" size="mini" @click="handleUpdate(row)">编辑</el-button>
        </template>
      </el-table-column>
    </el-table>
    <pagination
      v-show="total > 0"
      :total="total"
      :page.sync="listQuery.page"
      :limit.sync="listQuery.limit"
      @pagination="fetchData"
    />
    <!-- 弹出对话框,用于新建用户 -->
    <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
      <el-form
        ref="dataForm"
        :rules="rules"
        :model="temp"
        label-position="left"
        label-width="70px"
        style="width: 400px margin-left:50px"
      >
        <el-form-item label="昵称" prop="username">
          <el-input v-model="temp.username" />
        </el-form-item>
        <el-form-item label="密码" prop="password">
          <el-input v-model="temp.password" />
        </el-form-item>
        <el-form-item label="类型" prop="type">
          <el-select
            v-model="temp.type"
            class="filter-item"
            placeholder="Please select"
          ><el-option v-for="item in userTypeOptions" :key="item.key" :label="item.display_name" :value="item.key" /></el-select>
        </el-form-item>
        <el-form-item label="有效期" prop="timestamp">
          <el-date-picker
            v-model="temp.timestamp"
            type="datetime"
            placeholder="Please pick a date"
          />
        </el-form-item>
        <el-form-item label="备注">
          <el-input
            v-model="temp.remark"
            :autosize="{ minRows: 2, maxRows: 4 }"
            type="textarea"
            placeholder="Please input"
          />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取消</el-button>
        <el-button type="primary" @click="dialogStatus==='create'?createData():updateData()">确定</el-button>
      </div>
    </el-dialog>
    <!-- 弹出对话框,用于新建用户 end-->
  </div>
</template>

<script>
import { fetchList, createMember, updateMember } from '@/api/member'
import { parseTime } from '@/utils'
import Pagination from '@/components/Pagination' // secondary package based on el-pagination

const userTypeOptions = [
  { key: 'normal', display_name: '普通会员' },
  { key: 'vip', display_name: 'VIP' },
  { key: 'admin', display_name: '管理员' }
]

export default {
  components: { Pagination },
  filters: {
    statusFilter(status) {
      const statusMap = { published: 'success', draft: 'gray', deleted: 'danger'
      }
      return statusMap[status]
    },
    parseTime(time, cFormat) {
      return parseTime(time, cFormat)
    }
  },
  data() {
    return {
      list: null,
      listLoading: true,
      total: 0,
      listQuery: { page: 1, limit: 20, username: undefined, type: undefined, sort: '+id'
      },
      userTypeOptions,
      sortOptions: [{ label: 'ID Ascending', key: '+id' }, { label: 'ID Descending', key: '-id' }
      ],
      temp: { id: undefined, remark: '', timestamp: new Date(), username: '', password: '', type: ''},
      dialogFormVisible: false,
      dialogStatus: '',
      textMap: { update: '编辑', create: '新建' },
      // 编辑用户信息-表单验证
      rules: {
        username: [{
          required: true, message: 'username is required', trigger: 'blur' }],
        password: [{ required: true, message: 'password is required', trigger: 'blur' }],
        type: [{ required: true, message: 'type is required', trigger: 'change' }],
        timestamp: [{ type: 'date', required: true, message: 'timestamp is required', trigger: 'change' }]
      }
    }
  },
  created() {
    this.fetchData()
  },
  methods: {
    // get memebers list
    fetchData() {
      this.listLoading = true
      fetchList(this.listQuery).then(response => {
        this.list = response.data.items
        this.total = response.data.total
        setTimeout(() => { this.listLoading = false }, 500)
      })
    },
    handleFilter() {
      console.log('search', this.listQuery.username)
      this.fetchData()
    },

    // open the dialog
    handleCreate() {
      this.resetTemp()
      this.dialogStatus = 'create'
      this.dialogFormVisible = true
      this.$nextTick(() => {
        this.$refs['dataForm'].clearValidate()
      })
    },

    // add a memeber
    createData() {
      this.$refs['dataForm'].validate(valid => {
        if (valid) {
          this.temp.id = parseInt(Math.random() * 100) + 1024 // mock a id
          this.temp.author = 'vue-element-admin'
          createMember(this.temp).then(() => {
            this.list.unshift(this.temp)
            this.dialogFormVisible = false
            this.$notify({
              title: 'Success',
              message: 'Created Successfully',
              type: 'success',
              duration: 2000 })
          })
        }
      })
    },

    handleUpdate(row) {
      this.temp = Object.assign({}, row) // copy obj
      this.temp.timestamp = new Date(this.temp.timestamp)
      this.dialogStatus = 'update'
      this.dialogFormVisible = true
      this.$nextTick(() => {
        this.$refs['dataForm'].clearValidate()
      })
    },

    updateData() {
      this.$refs['dataForm'].validate(valid => {
        if (valid) {
          const tempData = Object.assign({}, this.temp)
          tempData.timestamp = +new Date(tempData.timestamp) // change Thu Nov 30 2017 16:41:05 GMT+0800 (CST) to 1512031311464
          updateMember(tempData).then(() => {
            const index = this.list.findIndex(v => v.id === this.temp.id)
            this.list.splice(index, 1, this.temp)
            this.dialogFormVisible = false
            this.$notify({
              title: 'Success',
              message: 'Update Successfully',
              type: 'success',
              duration: 2000
            })
          })
        }
      })
    },

    resetTemp() {
      this.temp = { id: undefined, remark: '', timestamp: new Date(), title: '', type: ''
      }
    }
  }
}
</script>

五、在/mock/index.js中注册新增的member。少了这一步,就会返回404错误代码。

import Mock from 'mockjs'
import { param2Obj } from '../src/utils'

import member from './member'

const mocks = [
  ...member
]

PS:如果想行高低点,可修改views/member/index.vue代码

<el-table
      v-loading="listLoading"
      :data="list"
      :row-style="{height:0+'px'}"
      :cell-style="{padding:0+'px'}"
      element-loading-text="Loading"
      border
      fit
      highlight-current-row
    >

 

以上亲测,可行。

posted @ 2020-06-17 23:53  世界因你而小  阅读(3011)  评论(0编辑  收藏  举报