271 lines
7.6 KiB
JavaScript
271 lines
7.6 KiB
JavaScript
import React, { Component } from 'react'
|
|
import { Button, Form, List, Pagination, Spin, Tooltip } from 'antd'
|
|
import { AntIcon } from 'components'
|
|
import { cloneDeep } from 'lodash'
|
|
|
|
const propsMap = ['autoLoad', 'loadData', 'pageIndex', 'pageSize']
|
|
|
|
/**
|
|
* 渲染查询栏
|
|
* @returns
|
|
*/
|
|
function renderQueryBar() {
|
|
const { query, moreQuery } = this.props
|
|
|
|
return (
|
|
<div className="yo-query-bar">
|
|
<Form
|
|
layout="inline"
|
|
ref={this.form}
|
|
onFinish={value => this.onQuery(value)}
|
|
initialValues={this.props.queryInitialValues}
|
|
>
|
|
{query}
|
|
<Form.Item>
|
|
<Button.Group className="mr-xs">
|
|
<Button htmlType="submit" type="primary" icon={<AntIcon type="search" />}>
|
|
查询
|
|
</Button>
|
|
<Tooltip placement="bottom" title="重置查询">
|
|
<Button
|
|
onClick={() => this.onResetQuery()}
|
|
icon={<AntIcon type="undo" />}
|
|
/>
|
|
</Tooltip>
|
|
</Button.Group>
|
|
{moreQuery && <Button>更多查询条件</Button>}
|
|
</Form.Item>
|
|
</Form>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default class QueryList extends Component {
|
|
state = {
|
|
loading: false,
|
|
dataSource: [],
|
|
|
|
ping: [],
|
|
}
|
|
|
|
// 查询表单实例
|
|
form = React.createRef()
|
|
|
|
// 查询值
|
|
query = {}
|
|
|
|
// 分页器配置
|
|
pagination = {
|
|
current: 1,
|
|
pageSize: 10,
|
|
total: 0,
|
|
size: 'small',
|
|
showSizeChanger: true,
|
|
showQuickJumper: true,
|
|
showTotal: total => `总共${total}条数据`,
|
|
}
|
|
|
|
// 默认选中页码
|
|
pageIndex = 1
|
|
// 默认页面尺寸
|
|
pageSize = 10
|
|
|
|
constructor(props) {
|
|
super(props)
|
|
|
|
this.autoLoad = typeof this.props.autoLoad === 'boolean' ? this.props.autoLoad : true
|
|
this.loadData =
|
|
typeof this.props.loadData === 'function' ? this.props.loadData : async () => {}
|
|
|
|
if (this.props.pageIndex) {
|
|
this.pageIndex = this.props.pageIndex
|
|
this.pagination.current = this.pageIndex
|
|
}
|
|
if (this.props.pageSize) {
|
|
this.pageSize = this.props.pageSize
|
|
this.pagination.pageSize = this.pageSize
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 自动加载数据
|
|
*/
|
|
componentDidMount() {
|
|
if (this.autoLoad) {
|
|
this.onLoadData()
|
|
}
|
|
|
|
window.addEventListener('resize', this.onResizeScroll)
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
window.removeEventListener('resize', this.onResizeScroll)
|
|
}
|
|
|
|
/**
|
|
* 加载数据
|
|
* 调用外部传入的loadData函数,可在loadData中自行改变参数
|
|
*/
|
|
onLoadData = async () => {
|
|
this.onLoading()
|
|
|
|
const res = await this.loadData(
|
|
{
|
|
pageIndex: this.pagination.current,
|
|
pageSize: this.pagination.pageSize,
|
|
},
|
|
cloneDeep(this.query)
|
|
)
|
|
|
|
this.setState(
|
|
{
|
|
dataSource: res.rows || res.data || res.items,
|
|
},
|
|
() => {
|
|
this.onResizeScroll()
|
|
}
|
|
)
|
|
|
|
this.pagination.total = res.totalCount
|
|
|
|
this.onLoaded()
|
|
}
|
|
|
|
/**
|
|
* 数据开始加载
|
|
*/
|
|
onLoading = () => {
|
|
this.setState({ loading: true })
|
|
}
|
|
|
|
/**
|
|
* 数据加载完成
|
|
*/
|
|
onLoaded = () => {
|
|
this.setState({ loading: false })
|
|
}
|
|
|
|
/**
|
|
* 进行查询
|
|
* 返回表单字段值,加载数据,并且返回到第一页
|
|
* @param {*} values
|
|
*/
|
|
onQuery = values => {
|
|
this.query = values
|
|
this.onReloadData(true)
|
|
}
|
|
|
|
/**
|
|
* 重置查询
|
|
* 初始化表单字段值,加载数据,并返回到第一页
|
|
*/
|
|
onResetQuery = () => {
|
|
this.form.current.resetFields()
|
|
this.query = {}
|
|
this.onReloadData(true)
|
|
}
|
|
|
|
/**
|
|
* 重新加载表格数据
|
|
* @param {Boolean} resetPage 是否重置页码
|
|
*/
|
|
onReloadData = (resetPage = false) => {
|
|
if (resetPage) {
|
|
this.pagination = {
|
|
...this.pagination,
|
|
current: this.pageIndex,
|
|
}
|
|
}
|
|
this.onLoadData()
|
|
}
|
|
|
|
onListChange = (current, pageSize) => {
|
|
this.pagination = {
|
|
...this.pagination,
|
|
current,
|
|
pageSize,
|
|
}
|
|
this.onLoadData()
|
|
}
|
|
|
|
onResizeScroll = () => {
|
|
this.onListScrollX({ target: this.refs['scroll-x'] })
|
|
}
|
|
|
|
onListScrollX(e) {
|
|
const { offsetWidth, scrollWidth, scrollLeft } = e.target
|
|
const ping = []
|
|
if (offsetWidth + scrollLeft < scrollWidth && scrollLeft > 0) {
|
|
ping.push(...['left', 'right'])
|
|
} else if (offsetWidth + scrollLeft < scrollWidth) {
|
|
ping.push('right')
|
|
} else if (offsetWidth + scrollLeft >= scrollWidth && offsetWidth < scrollWidth) {
|
|
ping.push('left')
|
|
}
|
|
this.setState({ ping })
|
|
}
|
|
|
|
render() {
|
|
const { loading, dataSource, ping } = this.state
|
|
|
|
const attrs = {}
|
|
Object.keys(this.props).forEach(key => {
|
|
if (!propsMap.includes(key)) {
|
|
attrs[key] = this.props[key]
|
|
}
|
|
})
|
|
|
|
const props = {
|
|
dataSource: this.state.dataSource,
|
|
rowKey: record => record.id || Math.random().toString(16).slice(2),
|
|
...attrs,
|
|
}
|
|
|
|
return (
|
|
<section>
|
|
{this.props.query && renderQueryBar.call(this)}
|
|
<div className="yo-action-bar">
|
|
<div className="yo-action-bar--actions">{this.props.operator}</div>
|
|
<div className="yo-action-bar--actions">
|
|
<Button.Group>
|
|
<Tooltip placement="bottom" title="刷新">
|
|
<Button
|
|
onClick={() => this.onReloadData()}
|
|
type="text"
|
|
icon={<AntIcon type="reload" />}
|
|
/>
|
|
</Tooltip>
|
|
</Button.Group>
|
|
</div>
|
|
</div>
|
|
<div className="yo-list">
|
|
<Spin spinning={loading} indicator={<AntIcon type="loading" />}>
|
|
<div
|
|
className={['yo-list-container', ...ping.map(p => `yo-list--ping-${p}`)]
|
|
.filter(p => p)
|
|
.join(' ')}
|
|
>
|
|
<div
|
|
className="yo-list--scroll"
|
|
ref="scroll-x"
|
|
onScroll={e => this.onListScrollX(e)}
|
|
>
|
|
<List {...props} />
|
|
</div>
|
|
</div>
|
|
{!!dataSource && !!dataSource.length && (
|
|
<Pagination
|
|
size="small"
|
|
{...this.pagination}
|
|
onChange={(current, pageSize) =>
|
|
this.onListChange(current, pageSize)
|
|
}
|
|
/>
|
|
)}
|
|
</Spin>
|
|
</div>
|
|
</section>
|
|
)
|
|
}
|
|
}
|