做后台项目,很多页面类似下面
这种页面有时候逻辑也是有点麻烦,要是每个页面一遍遍想,就有点尬,所以想了个偷懒的法子,将通用逻辑抽离出来,需要这种页面的时候,只需要适当的配置即可,不用再关心相同的逻辑。
对于表单,需要的方法有:设置表单数据、拿到表单的参数、设置表单项其他的属性等。
对于ajax请求回来的数据,需要的方法:拿到请求需要的参数,此参数分为两块,一个是表单提供的,一个分页和排序这种的,第一次的请求可以保留参数,为重置表单数据或者分页排序值做准备。
主要实现的通用功能:请求数据、查询逻辑、重置逻辑、导出逻辑。
query作为mixins的代码
github地址,运行node server.js
还有yarn install;yarn dev
,之后打开http://localhost:8080/single-query即可看到效果
<script>
/* 此页面最适合 上面是简单的表单,下面是表格,主要是查询 翻页 重置 导出功能
1. mixins写入此文件,import Query from 'xx';mixins:[Query]
2. formConfig colConfigs ajaxApis均需要特定配置,其他的根据情况吧
3. init里面一般是当前页面具体的初始化,一般需要重写
4. computed:tableData一般是需要重新写的
5. 放好html,基本可以玩起来了
*/
import EnhancedTable from '@/components/EnhancedTable'
import EnhancedForm from '@/components/EnhancedForm'
export default {
components: { EnhancedTable, EnhancedForm },
data () {
const formConfig = {
year: { label: '年份', category: 'date-picker', default: (new Date()).getFullYear() + '', type: 'year', format: 'yyyy', valueFormat: 'yyyy' },
term: { label: '季度', category: 'select', options: [{ value: '春', label: '春' }, { value: '夏', label: '夏' }, { value: '秋', label: '秋' }, { value: '冬', label: '冬' }] },
area: { label: '大区', category: 'select', filterable: true, default: '', options: null },
name: { label: '姓名', category: 'input' },
code: { label: '编号', category: 'input' }
}
const formAttr = {
// 行内显示
inline: true,
// 每个label宽
labelWidth: '100px',
// label右对齐
labelPosition: 'right'
}
const colConfigs = [
{ prop: 'orderNumber', label: '序号', sortable: false, align: 'center' },
{ slot: 'projectName', prop: 'projectName', label: '教研组', sortable: false, align: 'center' },
{ prop: 'teacherCount', label: '教师数量', sortable: false, align: 'center' },
{ prop: 'lessonCount', label: '总课次', sortable: false, align: 'center' },
{ prop: 'uploadPercent', label: '上传率', sortable: false, align: 'center' },
{ prop: 'passPercent', label: '合格率', sortable: false, align: 'center' }
]
const ajaxApis = {
query: 'AjaxQuery',
export: 'AjaxExport'
}
return {
// 查询表单项的配置
formConfig,
// 整个表单的统一配置
formAttr,
// 表格每列的配置
colConfigs,
// 这个是 请求的方法,不同页面的请求方法名肯定是不一样的 需要配置
ajaxApis,
// 表格的加载图标
isShowTableLoading: false,
// 表格请求的原始数据
tableDataNative: [],
// 有数据就意味着可能分页
otherParams: {
pageIndex: 0,
pageSize: 10,
isAsc: '',
sortBy: ''
},
// 数据总长度,基本只给分页组件用的
dataLength: 0,
// 为了方便重置,将首次请求表格数据的参数保存
initialParams: null
}
},
computed: {
// 处理之后的数据
tableData () {
return this.tableDataNative
}
},
mounted () {
this.init()
},
methods: {
// 页面加载执行的方法
async init () {
// 这个有异步操作,需要用await
await this.setAreaOptions()
this.setInitialParams()
this.getTableData()
},
setInitialParams () {
let formParams = this.getFormData()
// 设置首次查询的参数,这里注意对象是引用,必须深度复制下
this.initialParams = { formParams: { ...formParams }, otherParams: { ...this.otherParams } }
},
async setAreaOptions () {
let res = await this.$api.AjaxGetAreas()
let options = res.data.data
this.setSingleFormItem({ prop: 'area', attr: 'options', value: options })
this.setSingleFormItem({ prop: 'area', attr: 'default', value: options[1].value })
},
clickSearchBtn () {
// 重置页数的相关参数,这个是,比如你在点击第二页之后,pageIndex=2,但是当点击查询的时候,需要重新重置
this.otherParams = this.initialParams.otherParams
this.getTableData()
},
clickExportBtn () {
// 导出的参数和查询的参数基本一样,但是数据不分页
let params = { ...this.getAjaxQueryParams() }
params.pageSize = 0
this.$api[this.ajaxApis.export](params)
},
clickResetBtn () {
// 重置表单
this.setFormData(this.initialParams.formParams)
// 重置页数的相关参数
this.otherParams = this.initialParams.otherParams
// 查询
this.getTableData()
},
// ajax请求表格数据,并赋值,因为后端的数据很多时候前端需要处理下,在computed那边加一层过滤
async ajaxQuery (params) {
// 显示表单加载
this.isShowTableLoading = true
let res = await this.$api[this.ajaxApis.query](params)
this.isShowTableLoading = false
this.tableDataNative = res.data.data
this.dataLength = res.data.dataCount
},
// 将表单元素设置成特定的值,params = {year:2019,...}
setFormData (params, refForm = 'queryForm') {
// 表单
for (let key in params) {
this.$refs[refForm].$data.form.props[key] = params[key]
}
},
// 得到表单各项的值
getFormData (refForm = 'queryForm') {
return this.$refs[refForm].$data.form.props
},
// 设置单个表单元素的属性,除了默认值,常用的是options
setSingleFormItem ({ prop, attr, value, formConfig = 'formConfig', refForm = 'queryForm' }) {
this[formConfig][prop][attr] = value
// 默认值的话 需要变动form的属性
if (attr === 'default') {
this.$refs[refForm].$data.form.props[prop] = value
}
},
getTableData () {
let params = this.getAjaxQueryParams()
this.ajaxQuery(params)
},
// 请求的参数 包括表单和页数相关的数据
getAjaxQueryParams () {
let formParams = this.getFormData()
let params = { ...this.otherParams, ...formParams }
return params
},
// 改变页数
changeTablePage (page) {
this.otherParams.pageIndex = page
this.getTableData()
}
}
}
</script>
引用query的页面
<template lang="pug">
section
//- 表单区域
enhanced-form.app-query-form(ref="queryForm" :form-config="formConfig" :form-attr="formAttr")
template(v-slot:districtName="{config,form}")
el-form-item(:label="config.label" prop="districtName")
el-select(v-model="form.props.districtName" v-bind="config" @change="changeDistrict(form.props.districtName)")
el-option(v-for="item in config.options" :key="item.value" :value="item.value" :label="item.label" )
template(#btns)
el-form-item.app-btns-box
el-button.btn(type='primary', @click='clickSearchBtn') 查询
el-button.btn(type='primary', @click='clickResetBtn', plain='') 重置
el-button.btn(type='warning',plain='', @click='clickExportBtn') 导出
//- 表格区域
enhanced-table(:is-load='isShowTableLoading', :table-data='tableData', :col-configs='colConfigs')
//- 分页 没有数据的时候不显示
.pagination-box(v-if="tableData.length")
el-pagination(@current-change='changeTablePage', :current-page.sync='otherParams.pageIndex', :page-size='otherParams.pageSize', layout='prev, pager, next, jumper', :total='dataLength')
</template>
<script>
import Query from '@/mixins/Query'
export default {
mixins: [Query],
data () {
const formConfig = {
year: { label: '年份', category: 'date-picker', default: (new Date()).getFullYear() + '', type: 'year', format: 'yyyy', valueFormat: 'yyyy' },
term: { label: '季度', category: 'select', options: [{ value: '春', label: '春' }, { value: '夏', label: '夏' }, { value: '秋', label: '秋' }, { value: '冬', label: '冬' }] },
area: { label: '大区', category: 'select', filterable: true, default: '', options: null },
name: { label: '姓名', category: 'input' },
code: { label: '编号', category: 'input' }
}
const colConfigs = [
{ prop: 'orderNumber', label: '序号', sortable: false, align: 'center' },
{ slot: 'projectName', prop: 'projectName', label: '教研组', sortable: false, align: 'center' },
{ prop: 'teacherCount', label: '教师数量', sortable: false, align: 'center' },
{ prop: 'lessonCount', label: '总课次', sortable: false, align: 'center' },
{ prop: 'uploadPercent', label: '上传率', sortable: false, align: 'center' },
{ prop: 'passPercent', label: '合格率', sortable: false, align: 'center' }
]
const ajaxApis = {
query: 'AjaxQuery',
export: 'AjaxExport'
}
return {
// 查询表单项的配置
formConfig,
// 表格每列的配置
colConfigs,
// 这个是 请求的方法,不同页面的请求方法名肯定是不一样的 需要配置
ajaxApis
}
},
computed: {
// 处理之后的数据
tableData () {
return this.tableDataNative
}
},
methods: {
// 页面加载执行的方法
async init () {
// 这个有异步操作,需要用await
await this.setAreaOptions()
this.setInitialParams()
this.getTableData()
},
async setAreaOptions () {
let res = await this.$api.AjaxGetAreas()
let options = res.data.data
this.setSingleFormItem({ prop: 'area', attr: 'options', value: options })
this.setSingleFormItem({ prop: 'area', attr: 'default', value: options[1].value })
}
}
}
</script>
<style>
.el-table{
border:1px solid #e8e8e8;
width: 90%;
margin: auto;
}
.pagination-box{
margin-top: 20px;
text-align: center;
}
</style>
不足
水平有限,即便这样还是有点麻烦,嗯,继续加油