- A+
所属分类:Web前端
表单校验参考了https://blog.csdn.net/iamlujingtao/article/details/105186117
效果如图所示,主要做了一些美化和解决一些看着难受的点
代码如下,有时间再介绍
<template> <div class="app-container"> <div class="filter-container"> <el-input v-model="listQuery.car" placeholder="车辆id" style="width: 200px" class="filter-item" clearable @keyup.enter.native="handleFilter" /> <el-autocomplete v-model="listQuery.project" :fetch-suggestions="querySearchAsync" placeholder="项目名称" class="filter-item" clearable @clear="setBlur()" @keyup.enter.native="handleFilter" /> <el-date-picker v-model="listQuery.startTime" type="datetime" placeholder="选择开始日期时间" class="filter-item" :picker-options="pickerOptions" value-format="yyyy-MM-dd HH:mm:ss" /> <el-date-picker v-model="listQuery.endTime" type="datetime" placeholder="选择结束日期时间" class="filter-item" :picker-options="pickerOptions" value-format="yyyy-MM-dd HH:mm:ss" /> <el-button-group> <el-button class="filter-item" style="margin-left: 20px" icon="el-icon-search" plain round @click="handleFilter" > 搜索 </el-button> <el-button class="filter-item" style="margin-left: 10px" icon="el-icon-circle-plus-outline" plain round @click="add" > 新增 </el-button> </el-button-group> </div> <el-form ref="form" :model="form" :rules="rules"> <el-table v-loading="loading" :data="form.tableData" style="width: 100%" border fit> <el-table-column label="车辆" min-width="15%" prop="car" align="center"> <template v-slot="{row,$index}"> <template v-if="row.edit"> <el-form-item :prop="'tableData.'+$index+'.car'" :rules="rules.car"> <el-input v-model="row.car" clearable size="small" /> </el-form-item> </template> <span v-else>{{ row.car }}</span> </template> </el-table-column> <el-table-column label="项目" min-width="15%" prop="project" align="center"> <template v-slot="{row,$index}"> <template v-if="row.edit"> <el-form-item :prop="'tableData.'+$index+'.project'" :rules="rules.project"> <el-input v-model="row.project" clearable size="small" /> </el-form-item> </template> <span v-else>{{ row.project }}</span> </template> </el-table-column> <el-table-column label="开始日期" min-width="20%" align="center"> <template v-slot="{row,$index}"> <template v-if="row.edit"> <el-form-item :prop="'tableData.'+$index+'.startTime'" :rules="rules.startTime"> <el-date-picker v-model="row.startTime" type="datetime" placeholder="请选择日期" align="center" size="small" :picker-options="pickerOptions" value-format="yyyy-MM-dd HH:mm:ss" /> </el-form-item> </template> <template v-else> <i class="el-icon-time" /> <span>{{ row.startTime }}</span> </template> </template> </el-table-column> <el-table-column label="结束日期" min-width="20%" align="center"> <template v-slot="{row,$index}"> <template v-if="row.edit"> <el-form-item :prop="'tableData.'+$index+'.endTime'" :rules="rules.endTime"> <el-date-picker v-model="row.endTime" type="datetime" placeholder="请选择日期" align="center" size="small" :picker-options="pickerOptions" value-format="yyyy-MM-dd HH:mm:ss" /> </el-form-item> </template> <template v-else> <i class="el-icon-time" /> <span>{{ row.endTime }}</span> </template> </template> </el-table-column> <el-table-column label="操作" min-width="20%" align="center"> <template slot-scope="{row,$index}"> <template v-if="!row.edit"> <!--加div是为了和下面else中的button不一样,可以避免点击按钮后不失焦--> <div> <el-button id="edit-button" size="small" plain round icon="el-icon-edit" type="primary" @click="handleEdit(row)" > 修改 </el-button> <el-button :id="'deleteButton'+$index" size="small" style="margin-left: 15px" plain round icon="el-icon-delete" type="danger" @click="confirmDelete($index,row)" > 删除 </el-button> </div> </template> <template v-else> <el-button id="confirm-save-button" size="small" plain round icon="el-icon-circle-check" type="success" @click="confirmSave($index,row)" >{{ '保存' }} </el-button> <el-button id="cancel-save-button" style="margin-left: 15px" size="small" plain round icon="el-icon-circle-close" type="info" @click="cancelSave($index,row)" >{{ '取消保存' }} </el-button> </template> </template> </el-table-column> </el-table> </el-form> <pagination v-show="total > 0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" :page-sizes.sync="pageSizes" @pagination="getTableData" /> </div> </template> <script> import Pagination from '@/components/Pagination' // import api8899 from '@/api/api8899' export default { components: { Pagination }, data() { return { // 输入建议 restaurants: [], // 加载状态 loading: true, list: null, total: 0, listQuery: { page: 1, limit: 12, car: undefined, project: undefined, startTime: undefined, endTime: undefined }, pageSizes: [12, 24, 36], form: { tableData: [] }, rules: { car: [{ type: 'string', required: true, trigger: 'change', message: '车辆不能为空' }], project: [{ type: 'string', required: true, trigger: 'change', message: '项目不能为空' }], startTime: [{ type: 'string', required: true, trigger: 'change', message: '开始时间不能为空' }] }, // 时间选项 pickerOptions: { shortcuts: [ // { // text: '现在', // onClick (picker) { // picker.$emit('pick', new Date()) // } // }, { text: '昨天', onClick(picker) { const date = new Date() date.setTime(date.getTime() - 3600 * 1000 * 24) picker.$emit('pick', date) } }, { text: '三天前', onClick(picker) { const date = new Date() date.setTime(date.getTime() - 3600 * 1000 * 24 * 3) picker.$emit('pick', date) } }, { text: '七天前', onClick(picker) { const date = new Date() date.setTime(date.getTime() - 3600 * 1000 * 24 * 7) picker.$emit('pick', date) } }] } } }, mounted() { this.getTableData() this.inputSuggest() }, methods: { async getTableData() { // const res = await api8899.search_car(this.listQuery) // this.total = res.data.code === 200 ? res.data.data.count : 0 // this.form.tableData = res.data.data.data this.form.tableData = [ { car: 'Aaa012', projectId: 'aaa', project: '某个项目', startTime: '2021-09-21 13:51:43', endTime: '2021-09-26 13:51:43' }, { car: 'Aaa234', projectId: 'aaa', project: '某个项目', startTime: '2021-08-26 13:51:43', endTime: '' }, { car: 'Aaa345', projectId: 'bbb', project: '其他项目', startTime: '2021-07-26 13:51:43', endTime: '2021-07-26 13:51:43' }, { car: 'Aaa222', projectId: 'bbb', project: '其他项目', startTime: '2021-09-09 13:51:43', endTime: '' } ] this.form.tableData.map((v) => { this.$set(v, 'edit', false) // v.edit = false // 不能被v-if监听到 return v }) this.loading = false }, handleFilter() { this.loading = true this.getTableData() this.loading = false }, handleEdit(row) { if (row.temp === undefined) { row.temp = Object.assign({}, row) // 复制对象,为了取消修改后还原数据 } else if (row.temp.car === '') { delete row.temp row.temp = Object.assign({}, row) // 复制对象,为了取消修改后还原数据 } row.edit = !row.edit }, validateField(form, index) { let result = true for (const item of this.$refs[form].fields) { if (parseInt(item.prop.split('.')[1]) === index) { this.$refs.form.validateField(item.prop, (error) => { if (error) { result = false } }) } if (!result) break } return result }, async confirmSave(index, row) { if (!this.validateField('form', index)) { this.$message({ type: 'info', message: '保存修改失败,请检查是否有未填字段', center: true }) return } // 判断值是否有改变,如果没有则不做下面的操作 const tmp = Object.assign({}, row) const rowTmp = Object.assign({}, tmp.temp) delete rowTmp.edit delete tmp.temp delete tmp.edit if (JSON.stringify(rowTmp) === JSON.stringify(tmp)) { row.edit = !row.edit return } // 配置发送的请求参数 // const params = { // 'car': row.car, // 'project': row.project, // 'startTime': row.startTime, // 'endTime': row.endTime, // 'oCar': row.temp.car, // 'oProject': row.temp.project, // 'oStartTime': row.temp.startTime, // 'oEndTime': row.temp.endTime // } this.loading = true // const response = await api8899.upsert_car(params) const response = { 'data': { 'code': 200 }} // const response = { 'data': { 'code': 23423,'message':'自定义提示' }} this.loading = false let type, message if (response.data.code === 500) { type = 'error' message = '保存出错,请联系开发人员修复' } else if (response.data.code === 200) { type = 'success' message = '保存成功' } else { type = 'info' message = response.data.message } this.$message({ type: type, message: message, center: true }) // info为保存数据重复等问题,直接返回 if (type === 'info') { return } row.edit = !row.edit delete row.temp row.temp = Object.assign({}, row) // 复制对象,为了取消修改后还原数据 }, cancelSave(index, row) { if (row.temp.car === '') { this.$delete(this.form.tableData, index) return } this.$set(this.form.tableData, index, row.temp) // 取消后还原数据到修改前状态 }, // 删除数据 async confirmDelete(index, row) { // 让按钮失焦防止在提示时按多次enter键导致多次提交 document.getElementById('deleteButton' + index).blur() // 设置弹窗样式 const h = this.$createElement const confirmText1 = ['车辆 : ', '项目 : ', '开始时间 : ', '结束时间 : '] const confirmText2 = [row.car, row.project, row.startTime, row.endTime] const newData = [] for (const i in confirmText1) { newData.push(h('span', null, confirmText1[i])) newData.push(h('i', { style: 'color: teal' }, confirmText2[i])) newData.push(h('div', null, null)) } const confirm = await this.$msgbox({ title: '确定删除该条数据吗', message: h('p', null, newData), showCancelButton: true, confirmButtonText: '确定', cancelButtonText: '取消' }).catch(() => { this.$message({ type: 'info', message: '已取消删除', center: true }) }) if (confirm === 'confirm') { this.loading = true // const response = await api8899.delete_car({ 'car': row.car, 'project': row.project, 'startTime': row.startTime }) const response = { 'data': { 'code': 200 }} const type = response.data.code === 200 ? 'success' : 'error' const message = response.data.code === 200 ? '成功删除数据' : '删除数据失败,请联系开发人员修复' this.$delete(this.form.tableData, index) this.loading = false this.$message({ type: type, message: message, center: true }) } }, // 新增时重新初始化一个插入第一行 add() { const temp = { car: '', project: '', projectId: '', startTime: '', endTime: '', edit: true, temp: { car: '', project: '', startTime: '', endTime: '' } } this.form.tableData.unshift(temp) }, // 获取项目输入框建议 async inputSuggest() { // const tmp = await api8899.search_project() const tmp = { data: { data: [{ value: '某个项目b' }, { value: '某个项目a' }] }} this.restaurants = tmp.data.data }, // 处理输入框建议,restaurants必须是包含value属性的对象 [ {value:'xxx'} , ...] querySearchAsync(queryString, cb) { const restaurants = this.restaurants const results = queryString ? restaurants.filter(this.createStateFilter(queryString)) : restaurants cb(results) }, // 输入框建议过滤规则 createStateFilter(queryString) { return (state) => { return (state.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0) } }, // 清空输入框时取消聚焦 使用户重新点击来展示建议下拉框 setBlur() { document.activeElement.blur() } } } </script> <style scoped> .filter-container { text-align: left; padding-bottom: 10px; } .filter-item { display: inline-block; vertical-align: middle; margin-bottom: 10px; } .app-container { padding: 20px; } /deep/ .el-form-item { margin-bottom: 0 } /deep/ .el-input__inner { text-align: center; } /deep/ .el-button--text { display: none; } </style>