话不多说 直接看效果

代码如下:
<template>
<div>
<el-form ref="formRef" label-width="70px" :model="formData" autocomplete="on" @submit.prevent>
<el-row v-for="(item, index) in formData.querys" :key="index" :gutter="16" :xs="24">
<el-col :xs="24" :sm="9">
<el-form-item :label="'条件' + (index + 1) + ':'" :prop="'querys.' + index + '.column'">
<el-select
v-model="item['column']"
placeholder="请选择"
filterable
clearable
:loading="columnListLoading"
@change="handleColumnChange($event, item)"
>
<el-option
v-for="column in index === 0 ? columnStaticList : columnList"
:key="column.column_name"
:label="column.column_full_name"
:value="column.column_name"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="6">
<el-form-item
label-width="0"
:prop="'querys.' + index + '.op'"
:rules="{
required: true,
message: '该项为必填项',
trigger: 'blur',
}"
>
<el-select v-model="item['op']" placeholder="关系选择" filterable clearable>
<el-option
v-for="op in index === 0
? operateStringList
: item.column_type === 2
? operateStringList
: operateList"
:key="op.value"
:label="op.label"
:value="op.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="9">
<el-form-item
label-width="0"
:prop="'querys.' + index + '.value'"
:rules="{
required: true,
message: '该项为必填项',
trigger: 'blur',
}"
>
<el-select
v-if="index === 0"
v-model="item['value']"
placeholder="值选择"
style="width: calc(100% - 35px)"
filterable
clearable
:loading="appListLoading"
>
<el-option
v-for="app in appList"
:key="app.app_id"
:label="'[' + app.app_id + ']' + app.app_name"
:value="app.app_id"
/>
</el-select>
<el-datetime
v-else-if="item.column_type === 3"
v-model="item['value']"
style="width: calc(100% - 35px)"
type="datetime"
placeholder="选择日期"
/>
<el-input
v-else
v-model.trim="item['value']"
style="width: calc(100% - 35px)"
placeholder="请输入"
/>
<el-button
v-if="index !== 0"
type="danger"
class="btn-delete"
icon="el-icon-minus"
circle
@click="handleDeleteQuery(index)"
/>
</el-form-item>
</el-col>
</el-row>
<el-button type="primary" class="btn-add" plain @click="handleClick">+ 添加</el-button>
<el-divider />
<el-button type="primary" @click="dialogSettingFormState = true">显示字段配置</el-button>
<el-button type="primary" :loading="exportLoading" @click="handleExportExcel">导出</el-button>
<el-button type="primary" @click="handleSearch">查询</el-button>
</el-form>
<Table
v-model:page="currentPage"
v-model:limit="limit"
v-loading="tableDataLoading"
style="margin-top: 16px"
:data="tableData"
:total="total"
@pagination="handleSearch"
>
<el-table-column
v-for="item in customTableHeaders"
:key="item.column_name"
:prop="item.column_name"
:label="item.column_full_name"
/>
</Table>
<dialogSettingForm
v-model="dialogSettingFormState"
@handle-setting="customTableHeaders = $event"
/>
</div>
</template>
<script>
import { getDataPrivilegeScheme } from '@/api/common'
import { getSearchProjectColumn, getSearchProject } from '@/api/userManage'
import dialogSettingForm from './dialogSettingForm.vue'
export default {
components: {
dialogSettingForm,
},
data() {
return {
formData: {
querys: [
{
column: 'pt_register_app_ht_1d_d_o',
op: 5,
value: null,
column_type: 1,
},
],
},
columnStaticList: [
{
column_name: 'pt_register_app_ht_1d_d_o', // 字段名
column_full_name: '注册应用', // 字段中文名
column_type: 1, // 字段类型
},
{
column_name: 'pt_last_login_app_ht_1d_d_o', // 字段名
column_full_name: '最后登录应用', // 字段中文名
column_type: 1, // 字段类型
},
],
columnList: [],
columnListLoading: false,
appList: [],
appListLoading: false,
operateList: [
{
label: '大于',
value: 1,
},
{
label: '小于',
value: 2,
},
{
label: '大于等于',
value: 3,
},
{
label: '小于等于',
value: 4,
},
{
label: '等于',
value: 5,
},
{
label: '不等于',
value: 6,
},
],
operateStringList: [
{
label: '等于',
value: 5,
},
],
customTableHeaders: JSON.parse(localStorage.getItem('userCircleTypeList')) || [],
// 表格数据
tableData: [],
tableDataLoading: false,
// 分页
total: 0,
currentPage: 1,
limit: 50,
dialogSettingFormState: false,
exportLoading: false,
}
},
mounted() {
this.handleAppList()
this.handleProjectColumn()
},
methods: {
handleAppList() {
this.appListLoading = true
getDataPrivilegeScheme(2, 3)
.then((res) => {
if (res.code === 200) {
this.appList = res.data
}
this.appListLoading = false
})
.catch(() => {
this.appListLoading = false
})
},
handleProjectColumn() {
this.columnListLoading = true
getSearchProjectColumn(1)
.then((res) => {
if (res.code === 200) {
this.columnList = res.data
}
this.columnListLoading = false
})
.catch(() => {
this.columnListLoading = false
})
},
handleClick() {
this.formData.querys.push({
column: null,
op: null,
value: null,
column_type: null,
})
},
handleColumnChange(data, item) {
const currentObj = this.columnList.find((item) => item.column_name === data)
item.column_type = currentObj.column_type
},
handleDeleteQuery(index) {
this.formData.querys.splice(index, 1)
},
handleSearch() {
if (!this.customTableHeaders.length) {
this.$message.info('请先点击"显示字段配置"')
return
}
this.$refs['formRef'].validate((valid) => {
if (valid) {
this.tableDataLoading = true
const columns = this.customTableHeaders.map((item) => item.column_name)
getSearchProject(1, columns, this.formData.querys, this.currentPage, this.limit)
.then((res) => {
if (res.code === 200) {
this.tableData = res.data.records
this.total = res.data.total
}
this.tableDataLoading = false
})
.catch(() => {
this.tableDataLoading = false
})
} else {
return false
}
})
},
// 导出Excel
handleExportExcel() {
this.$refs['formRef'].validate((valid) => {
if (valid) {
this.exportLoading = true
import('@/utils/Export2Excel').then((excel) => {
// 拉取全部数据
const columns = this.customTableHeaders.map((item) => item.column_name)
getSearchProject(1, columns, this.formData.querys, 1, 10000)
.then((res) => {
if (res.code === 200) {
const tHeader = this.customTableHeaders.map((item) => item.column_full_name)
const filterVal = columns
const data = this.formatJson(filterVal, res.data.records)
excel.export_json_to_excel({
header: tHeader,
data,
filename: '用户数据',
})
this.exportLoading = false
} else {
this.exportLoading = false
}
})
.catch(() => {
this.exportLoading = false
})
})
} else {
return false
}
})
},
// 导出Excel格式化JSON
formatJson(filterVal, jsonData) {
return jsonData.map((v) => filterVal.map((j) => v[j]))
},
},
}
</script>
<style lang="scss" scoped>
.el-input,
.el-select {
width: 100%;
}
.btn-add {
width: 100%;
border-style: dashed;
}
.btn-delete {
min-height: 22px;
padding: 0 4px;
margin-left: 10px;
}
</style>

本文展示了如何使用Element UI构建动态查询表单,通过el-select组件进行字段选择,操作选择,并实现数据过滤和导出Excel。通过实例代码详细讲解了表格配置、条件设置和导出功能的实现。
1478





