一、先建一个 ListQueryForm.vue
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<template>
<div class="search_box">
<template v-if="formItems.length">
<zk-form
id="listQueryForm"
ref="refListQueryForm"
:label-width="labelWidth"
:label-position="labelPosition"
:model="listQueryForm">
<!-- :item-min-width="268"-->
<zk-flexbox
handler
:col-max-number="colMaxNum"
:item-min-width="itemMinWidth"
:gutter="[6, 8]">
<zk-flexbox-item
v-for="item in formItems"
:key="item.key"
v-if="!item.isHidden">
<template
<!-- isHidden 是否隐藏 -->
<zk-form-item :prop="item.model">
<template slot="label">
<span v-if="item.bindingConfig.required" class="zk-form-item__required">*</span>
{{ item.bindingConfig.label }}
<zk-popover
v-if="item.bindingConfig.labelIntact"
trigger="hover"
:content="item.bindingConfig.labelIntact">
<i class="zds-icon-warning-filled" slot="reference"> </i>
</zk-popover>
</template>
<zk-select
v-if="item.type === 'select'"
v-model="item.value"
:placeholder="$tc('common.pleaseSelect')"
:size="item.bindingConfig.size"
:disabled="item.bindingConfig.disabled"
:multiple="item.bindingConfig.multiple"
:clearable="!item.bindingConfig.required"
filterable
:collapse-tags="item.bindingConfig.multiple"
:multiple-limit="item.bindingConfig.multipleLimit"
:all-select="item.bindingConfig?.allSelect !== undefined ? item.bindingConfig.allSelect : item.bindingConfig.multiple"
popper-class="option_a"
@change="bindChange(item)"
:filter-method="dataFilter">
<zk-option
v-for="opt in item.options"
:key="opt.value"
:label="opt.label"
:value="opt.value" />
</zk-select>
<zk-input
v-if="item.type === 'input'"
v-model="item.value"
:placeholder="$tc('common.pleaseInput')"
clearable
@blur="blurValue(item)"
@pressEnter="onSearch(item)">
<span
v-if="item.bindingConfig.isBatch"
slot="suffix"
@click="bacthHandle(item)">
<i
class="zds-icon-edit-filled"
title="Please use coma to seperate goodscode" />
</span>
</zk-input>
<zk-input
v-if="item.type === 'textarea'"
v-model="item.value"
clearable
:maxlength="item.bindingConfig.maxlength"
show-word-limit
:placeholder="$tc('common.pleaseInput')"
rows="3">
</zk-input>
<zk-date-picker
v-if="item.type === 'year'"
v-model="item.value"
type="year"
:placeholder="$tc('common.pleaseSelect')"
clearable></zk-date-picker>
<zk-date-picker
v-if="item.type === 'monthrange'"
v-model="item.value"
type="month-range"
clearable
:placeholder="$tc('common.pleaseSelect')"
:picker-options="item.bindingConfig.pickerOptions"></zk-date-picker>
<zk-date-picker
v-if="item.type === 'datePicker'"
v-model="item.value"
type="daterange"
:picker-options="item.bindingConfig.pickerOptions"
clearable />
<zk-date-picker
v-if="item.type === 'datetimerange'"
v-model="item.value"
type="datetimerange"
:placeholder="$tc('common.pleaseSelect')"
:picker-options="item.bindingConfig.pickerOptions"
clearable />
<zk-cascader
v-if="item.type === 'cascader'"
:placeholder="$tc('common.pleaseSelect')"
:data="item.options"
v-model="item.value"
clearable
filterable
:props="{ expandTrigger: 'hover' }"></zk-cascader>
<div v-if="item.type === 'slot'">
<slot :name="item.slot" :scope="item" />
</div>
</zk-form-item>
</template>
</zk-flexbox-item>
<template
<!-- style="margin-top: 14px;" -->
<zk-form-item>
<zk-button plain type="secondary" @click="onReset">
{{ $tc('common.reset') }}
</zk-button>
<zk-button type="outline" @click="onSearch" class="search_btn">
{{ $tc('common.search') }}
</zk-button>
</zk-form-item>
</template>
</zk-flexbox>
</zk-form>
</template>
<zk-modal
v-model="visible"
:title="$tc('common.Search in batch')"
top="100px"
width="700px"
@on-cancel="batchCancel"
@on-ok="batchOk">
<div class="pure_flex">
<p style="margin: 0 0 8px 0;">
{{ batchTitle }}:
</p>
<zk-input
v-model="batchValues"
type="textarea"
:placeholder="$tc('common.Please use coma to seperate')"
rows="8"
clearable />
</div>
</zk-modal>
</div>
</template>
<script>
export default {
name: 'ListQueryFormZeeKr',
props: {
labelWidth: {
type: String,
default: '120px',
},
labelPosition: {
type: String,
default: 'top',
},
// 筛选条件配置项
formItems: {
type: Array,
required: true,
},
// 表格数据
tableData: {
type: Array,
default: () => [],
},
colMaxNum: {
type: Number,
default: 4,
},
itemMinWidth: {
type: Number,
default: 280,
},
},
data() {
return {
listQueryForm: {},
// 是否显示批量模态框
visible: false,
// 批量模态框标题
batchTitle: '',
// 批量输入的值
batchValues: '',
// 当前点击批量输入的 对象
batchObj: {},
resetParams: {},
}
},
mounted() {
this.initForm()
},
methods: {
initForm() {
this.formItems.forEach((item) => {
this.resetParams[item.model] = item.value
})
},
onSelectChange(data) {
this.$emit('onSelectChange', data)
},
// 查询
onSearch() {
this.$emit('onSearch', this.formItems)
},
blurValue(item) {
if (item.bindingConfig.isBatch) {
item.value = this.commaSeparated(item.value)
}
},
// 重置
onReset() {
this.formItems.forEach((item) => {
if (item.default) {
item.value = item.default
} else if (!item.bindingConfig.disabled) {
item.value = item.value instanceof Array ? [] : ''
}
item.bindingConfig.onChange && item.bindingConfig.onChange(item)
})
this.$emit('onReset')
},
// 取消批量输入
batchCancel() {
this.batchValues = ''
this.visible = false
},
// 批量输入确定
batchOk() {
this.batchObj.value = this.commaSeparated(this.batchValues)
this.visible = false
this.onSearch()
},
// 过滤输入内容
commaSeparated(data) {
let str = data.replace(/[ ,\n]/g, ',')
const parts = str.split(',')
// Filter out empty strings
const filteredParts = parts.filter((part) => part !== '')
// Join the filtered parts back into a string
return filteredParts.join(',')
},
// 批量输入
bacthHandle(item) {
this.batchValues = item.value || ''
this.batchTitle = item.bindingConfig.label
this.batchObj = item
this.visible = true
},
// 筛选条件选中数据变更触发的事件
bindChange(item) {
item.bindingConfig.onChange && item.bindingConfig.onChange(item)
},
// 支持大小写字母查询
dataFilter(keyword, value, label) {
// 自定义搜索的方法,返回true展示
return label.toLowerCase().search(keyword.toLowerCase()) > -1
},
},
}
</script>
<style lang="less">
@import "./index.less"
.search_box {
background: var(--color_bg-primary)
// margin-top: 10px
.zk-page-container__content {
padding: 11px 20px !important
}
.hide .zk-form-item__label-text {
font-size: 0
}
.zk-form-item--placeholder {
margin-bottom: 0
}
.zds-icon-warning-filled {
font-size: 16px
}
}
.search_btn {
background: var(--color_bg-primary)
}
</style>
2. 如果在list.vue 里使用
<template>
<ListQueryForm
ref="form"
:form-items="formItems"
:itemMinWidth="268"
@onSearch="onReset"
:colMaxNum="5"
@onReset="onReset" />
</template>
<script>
import ListQueryForm from '@/components/ListQueryForm/index.vue';
import { formItems } from './config.js';
data() {
return {
formItems: [],
};
},
async mounted() {
this.formItems = await formItems(this);
},
</script>
3. 配置confin.js 文件
import { getZoneTree, queryCompanyBaseList } from '@/api/modules/claimRebatePayment'
import i18n from '@/locale'
function getRegionList(list) {
getZoneTree({
zoningNodeType: 'COUNTRY',
useHeaderPrincipal: true,
isChild: true
}).then(res=> {
let regionList = []
res.forEach(item => {
regionList = [...regionList, ...item.childList]
})
regionList.forEach(item => {
item.label = item.zoningName
item.value = item.zoningCode
})
list.find((item) => item.model === 'regionList').options = regionList
getCountryList([], list, regionList)
})
}
function getCountryList(regionList, list) {
const countryOpts = []
const regionOpts = list.find((item) => item.model === 'regionList').options
if (regionList?.length) {
regionList.forEach(region => {
const index = regionOpts.findIndex(item => item.zoningCode === region)
countryOpts.push(...regionOpts[index].childList)
})
} else {
(regionOpts || []).forEach(item => {
countryOpts.push(...item.childList)
})
}
countryOpts.forEach(item => {
item.label = item.zoningName
item.value = item.zoningCode
})
list.find((item) => item.model === 'countryList').options = countryOpts
getCompanyOpts( list)
}
function getCompanyOpts(list) {
const areaZoningCodeList = list.find((item) => item.model === 'regionList').value
const countryZoningCodeList = list.find((item) => item.model === 'countryList').value
queryCompanyBaseList({
areaZoningCodeList,
countryZoningCodeList,
}).then(res => {
let companyOpts = []
if (res.length) {
companyOpts = res.map(item => ({
label: item.companyName,
value: item.companyCode,
}))
list.find((item) => item.model === 'companyList').options = companyOpts
}
console.log(res, '===res')
})
}
export const formItems = async (self) => {
const list = [
{
type: 'input',
model: 'intentionNoList',
value: '',
bindingConfig: {
label: i18n.tc('Policy Application NO.'),
isBatch: true,
},
},
{
type: 'select',
model: 'intentionType',
value: '',
bindingConfig: {
label: i18n.tc('Rebate Type'),
multiple: false,
},
options: self.rebateTypeDataMap,
},
{
type: 'select',
model: 'regionList',
value: [],
bindingConfig: {
label:i18n.tc('Region'),
multiple: true,
onChange: (ls) => {
list.find((item) => item.model === 'countryList').options = []
list.find((item) => item.model === 'companyList').options = []
list.find((item) => item.model === 'countryList').value = []
list.find((item) => item.model === 'companyList').value = []
getCountryList(ls.value, list)
},
},
options:[],
},
{
type: 'select',
model: 'countryList',
value: [],
bindingConfig: {
label: i18n.tc('Countries'),
multiple: true,
onChange: (ls) => {
list.find((item) => item.model === 'companyList').options = []
list.find((item) => item.model === 'companyList').value = []
getCompanyOpts(list )
},
},
options: [],
},
{
type: 'select',
model: 'companyList',
value: [],
bindingConfig: {
label:i18n.tc('Company'),
multiple: true,
},
options: [],
},
{
type: 'select',
model: 'status',
value: '',
bindingConfig: {
label: i18n.tc('Approval Status'),
multiple: false,
},
options: self.statusOpts,
},
]
getRegionList(list)
return list
}