// 核心库 import React, { Component } from 'react' import { connect } from 'dva' // 组件库 import { Form, Button } from 'antd' import IFComponent from '../common/IFComponent' import UserCustomSearchEditModel from './UserCustomSearchEditModel' // 工具库 import { isEqual } from 'lodash' import { getDataFieldValue, setDataFieldValue } from '../utils/common' import storage from '../utils/storage' import getControl from '../utils/getControl' import { getFieldConfigs, getRuleByFieldConfigs } from '../utils/getFieldConfigs' class AdvanceSearch extends Component { constructor (props) { super(props) this.state = { data: {}, fieldConfigs: [], isShowContent: false // 展开收起 } // 搜索条件共享与记忆 const { filterItem = {}, filterList = [], maxShowContentNum = 4 } = props const { ID, SHARE_KEY, IS_REMEMBER } = filterItem this.insRef = ID // 当前 Search 组件的唯一标识 this.insRefs = filterList.map(item => item.ID) // 同 filterList 组里面所有的 AdvanceSearch 组件标识 this.shareKey = SHARE_KEY // 共享数据标识 this.isRemember = IS_REMEMBER // 是否记忆搜索条件 // 展开收起阈值 this.maxShowContentNum = maxShowContentNum } componentDidMount () { const { preventDefaultSearch, onRef, fields, presetValue } = this.props // 只在初次加载时,提取本地存储的共享查询条件作为预设值 this.setFieldConfigs({ fields, presetValue: this.checkPresetValue(presetValue) }, () => { !preventDefaultSearch && this.handleSearch() }) onRef instanceof Function && onRef(this) } UNSAFE_componentWillReceiveProps (nextProps) { if (!isEqual(nextProps.fields, this.props.fields) || !isEqual(nextProps.presetValue, this.props.presetValue)) { const { fields, presetValue } = nextProps this.setFieldConfigs({ fields, presetValue }, this.handleSearch) } } componentWillUnmount () { // 组件销毁时清空当前共享实例 if (this.shareKey) { this.props.dispatch({ type: 'search/cleanShareIns', payload: { key: this.shareKey, insRef: this.insRef } }) } // 如果不记住查询条件,则组件销毁时,清空共享数据 if (this.shareKey && !this.isRemember) { this.props.dispatch({ type: 'search/setShareData', payload: { key: this.shareKey, data: [] } }) storage('session').removeItem(this.shareKey) } } // 相同 formCode 的搜索组件共享搜索条件 setShareIns = (self = true) => { const { search, dispatch } = this.props let stopSelfChangeSearch = false let stopSelfExtraSearch = false console.log('共享搜索条件', this.shareKey) if (this.shareKey) { const instances = search.shareIns[this.shareKey] || [] // 同一 filterList 组里面的 Search 组件不共享搜索条件 const targetIns = instances.filter(ins => ins.insRef !== this.insRef && this.insRefs.indexOf(ins.insRef) === -1) if (targetIns.length) { // 设置自身状态 if (self) { // 配置的查询条件 const { instance } = targetIns[0] const { fieldConfigs: insFieldConfigs = [], data: insData = {} } = instance.state || {} const { fieldConfigs: thisFieldConfigs = [], data: thisData = {} } = this.state thisFieldConfigs.forEach(item => { // 拥有相同的编码 code 或者 field 字段,就表示查询项需要共享查询条件 const find = insFieldConfigs.find(ifc => (item.code && ifc.code === item.code) || ifc.field === item.field) // 默认显示的查询条件才允许共享查询 if (find && item.isDefaultQuery) { const setValue = getDataFieldValue(insData, find.id) if (Object.keys(insData).length) { item.value !== setValue && (stopSelfChangeSearch = true) item.value = setValue thisData[item.id] = setValue } } }) // 自定义添加的额外查询条件 const { getExtraData: insGetExtraData } = instance.props || {} const { setExtraData: thisSetExtraData, getExtraData: thisGetExtraData } = this.props if (insGetExtraData instanceof Function && thisSetExtraData instanceof Function && thisGetExtraData instanceof Function) { const insExtraData = insGetExtraData() const thisExtraData = thisGetExtraData() stopSelfExtraSearch = !isEqual(insExtraData, thisExtraData) } // 先判断额外搜索条件,额外搜索成立,则调用thisSetExtraData,并在回调中继续调用搜索 if (stopSelfExtraSearch) { thisSetExtraData(insGetExtraData(), this.handleSearch) } else if (stopSelfChangeSearch) { // fieldConfigs 搜索成立,则调用 setState(因为之前在配置的查询条件中是直接更改 state 的),回调中继续调用搜索 this.setState({ ...this.state }, this.handleSearch) } } else { // 设置其他关联的Search组件状态 let stopChangeSearch = false let stopExtraSearch = false targetIns.forEach(({ instance }) => { // 配置的查询条件 const { fieldConfigs: insFieldConfigs = [], data: insData = {} } = instance.state || {} const { fieldConfigs: thisFieldConfigs = [], data: thisData = {} } = this.state insFieldConfigs.forEach(item => { // 拥有相同的编码 code 或者 field 字段,就表示查询项需要共享查询条件 const find = thisFieldConfigs.find(tfc => (item.code && tfc.code === item.code) || tfc.field === item.field) // 默认显示的查询条件才允许共享查询 if (find && item.isDefaultQuery) { const setValue = getDataFieldValue(thisData, find.id) if (Object.keys(thisData).length) { item.value !== setValue && (stopChangeSearch = true) item.value = setValue insData[item.id] = setValue } } }) // 自定义添加的额外查询条件 const { setExtraData: insSetExtraData, getExtraData: insGetExtraData } = instance.props || {} const { getExtraData: thisGetExtraData } = this.props if (thisGetExtraData instanceof Function && insSetExtraData instanceof Function && insGetExtraData instanceof Function) { const thisExtraData = thisGetExtraData() const insExtraData = insGetExtraData() stopExtraSearch = !isEqual(thisExtraData, insExtraData) } // 先判断额外搜索条件,额外搜索成立,则调用thisSetExtraData,并在回调中继续调用搜索 if (stopExtraSearch) { insSetExtraData(thisGetExtraData(), instance.handleSearch) } else if (stopChangeSearch) { // fieldConfigs 搜索成立,则调用 setState(因为之前在配置的查询条件中是直接更改 state 的),回调中继续调用搜索 instance.setState({ ...instance.state }, instance.handleSearch) } }) } } // 存储当前 Search 组件实例 dispatch({ type: 'search/setShareIns', payload: { key: this.shareKey, insRef: this.insRef, instance: this } }) // 存储当前 shareKey 的查询数据 dispatch({ type: 'search/setShareData', payload: { key: this.shareKey, data: this.state.fieldConfigs } }) storage('session').setItem(this.shareKey, this.state.fieldConfigs) } return stopSelfChangeSearch || stopSelfExtraSearch } // 提取本地存储的共享查询条件作为预设值 checkPresetValue = (presetValue) => { const { search } = this.props const presetFieldConfigs = search.shareData[this.shareKey] || storage('session').getItem(this.shareKey).val const localPreset = {} if (Array.isArray(presetFieldConfigs)) { presetFieldConfigs.forEach(({ code, field, value }) => { // 编码 code 作为查询项共享查询条件的附加标识,因为有些查询项的 field 不一样,但又需要共享查询条件,所以额外配置 code 编码, // 当多个查询项拥有相同的编码 code 时,视为这些查询项需要共享查询条件 code && (localPreset[code] = value) field && (localPreset[field] = value) }) } return Object.assign(localPreset, presetValue) } // 处理父组件传下来的 fields setFieldConfigs = ({ fields, presetValue }, callback) => { const fieldConfigs = [] if (fields && fields.length) { fields.sort((x, y) => x.NUM - y.NUM) fields.forEach(item => { if (!item.USER_C_C_QUERY_GROUP_ID) { const config = getFieldConfigs({ field: item, onLoadData: this.onLoadData, onPressEnter: this.onPressEnter, onSelect: this.onDropDownPaginationSelect, onChange: this.onChange, onSearchRef: this.handleSearch }) fieldConfigs.push(config) } }) } // 赋值 data { field: value } const data = {} fieldConfigs.forEach(item => { if (presetValue !== undefined && typeof presetValue === 'object' && Object.keys(presetValue).length) { // 拥有相同编码 code 的查询项共享查询条件 if (Object.prototype.hasOwnProperty.call(presetValue, item.code)) { data[item.id] = presetValue[item.code] return } if (Object.prototype.hasOwnProperty.call(presetValue, item.field)) { data[item.id] = presetValue[item.field] return } } if (item.defaultValue !== undefined) { data[item.id] = item.defaultValue } }) this.saveFieldConfigs(fieldConfigs) this.setState({ data, fieldConfigs }, callback) } // field change 时候赋值给 data onChange = (params) => { const { value, colConfig } = params const data = { ...this.state.data } setDataFieldValue(data, colConfig.id, value) this.setState({ data }) } // 提供给分页下拉 下拉树选择 级联组件调用(详见 getControl.js),以获取上述组件的树数据,用于导出 table 时,获取到查询数据,并生成导出标题 onLoadData = (id, data) => { const targetFieldConfig = this.state.fieldConfigs.find(item => item.id === id) if (targetFieldConfig) { targetFieldConfig.dataSource = data this.saveFieldConfigs(this.state.fieldConfigs) } } // 将对应 formCode 的 fieldConfigs 存到 store 中,用于导出 table 时获取到查询数据,并生成导出标题 saveFieldConfigs = (fieldConfigs) => { const { formCode, dispatch } = this.props if (formCode) { dispatch({ type: 'search/setFieldConfigs', payload: { key: formCode, data: fieldConfigs } }) } } // 回车搜索 onPressEnter = ({ e: evt }) => { evt.stopPropagation() this.handleSearch(false) } // 提供给分页下拉的回调 onDropDownPaginationSelect = (params) => { const { record, complete, colConfig } = params || {} const data = { ...this.state.data } setDataFieldValue(data, colConfig.id, record ? record.ID : null) setDataFieldValue(data, `selectedRecord.${colConfig.id}`, record) this.setState({ data }, () => complete instanceof Function && complete()) } /** * 执行搜索,搜索流程为: * 调用 Search 组件 onSearch 方法, * 然后 Search 分别通过 ref 分别调用 AdvanceSearch 和 SearchGroupField 的 getSearchParams 方法获取到搜索参数, * 最后再由 Search 组件完成搜索操作,这样搜索就统一在 Search 中做了 * @param {*} self 设置自身状态还是设置共享状态 */ handleSearch = (self = true) => { if (this.setShareIns(self)) return console.log('调用查询开始', 1) const { onSearch } = this.props onSearch instanceof Function && onSearch() } // 获取搜索参数 提供给 ref 调用 getSearchParams = (rules = [], groups = []) => { return getRuleByFieldConfigs(this.state.data, this.state.fieldConfigs, rules, groups,this.props.user) } render () { const { fieldConfigs = [], data, isShowContent } = this.state const { formCode, formId, code, iconEle, extraInsertPlace, extraSearch = [], onEditModalClose, onAddGroupConfig } = this.props let extraFieldConfigs = extraInsertPlace === 'after' ? fieldConfigs.concat(extraSearch.map(extra => ({ extraSearch: true, extra }))) : extraSearch.map(extra => ({ extraSearch: true, extra })).concat(fieldConfigs) extraFieldConfigs = extraFieldConfigs.filter(item => item.isDefaultQuery || item.extraSearch) let showFieldConfigs = extraFieldConfigs if (showFieldConfigs.length > this.maxShowContentNum - 1) { showFieldConfigs = isShowContent ? extraFieldConfigs : extraFieldConfigs.slice(0, this.maxShowContentNum - 1) } return (
{ showFieldConfigs.map(item => { if (item.extraSearch) return item.extra item.value = getDataFieldValue(data, item.id) return ( {item.isRequire ? * : null}{item.label}} > {getControl(item, null, this)} ) }) }
{iconEle}
) } } export default connect(({ search }) => ({ search }))(AdvanceSearch)