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 >
以上亲测,可行。