update 响应式处理
This commit is contained in:
@@ -43,6 +43,8 @@ export default class QueryList extends Component {
|
||||
state = {
|
||||
loading: false,
|
||||
dataSource: [],
|
||||
|
||||
ping: [],
|
||||
}
|
||||
|
||||
// 查询表单实例
|
||||
@@ -91,6 +93,12 @@ export default class QueryList extends Component {
|
||||
if (this.autoLoad) {
|
||||
this.onLoadData()
|
||||
}
|
||||
|
||||
window.addEventListener('resize', this.onResizeScroll)
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('resize', this.onResizeScroll)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,9 +116,14 @@ export default class QueryList extends Component {
|
||||
this.query
|
||||
)
|
||||
|
||||
this.setState({
|
||||
dataSource: res.rows || res.data || res.items,
|
||||
})
|
||||
this.setState(
|
||||
{
|
||||
dataSource: res.rows || res.data || res.items,
|
||||
},
|
||||
() => {
|
||||
this.onResizeScroll()
|
||||
}
|
||||
)
|
||||
|
||||
this.pagination.total = res.totalCount
|
||||
|
||||
@@ -174,7 +187,26 @@ export default class QueryList extends Component {
|
||||
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)) {
|
||||
@@ -206,9 +238,21 @@ export default class QueryList extends Component {
|
||||
</div>
|
||||
</div>
|
||||
<div className="yo-list">
|
||||
<Spin spinning={this.state.loading} indicator={<AntIcon type="loading" />}>
|
||||
<List {...props} />
|
||||
{!!this.state.dataSource && !!this.state.dataSource.length && (
|
||||
<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}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { Component } from 'react'
|
||||
import { Breadcrumb, Empty, Input, Layout, Spin, Tooltip, Tree } from 'antd'
|
||||
import { Breadcrumb, Button, Col, Empty, Input, Layout, Row, Spin, Tooltip, Tree } from 'antd'
|
||||
import { AntIcon, Container } from 'components'
|
||||
import { SIDER_BREAK_POINT } from 'util/global'
|
||||
|
||||
function generateKey(data, level) {
|
||||
const n = level || [0]
|
||||
@@ -23,7 +24,7 @@ function generateList(data) {
|
||||
this.list.push({
|
||||
key,
|
||||
[this.replaceFields.value]: data[i][this.replaceFields.value],
|
||||
[this.replaceFields.title]: data[i][this.replaceFields.title]
|
||||
[this.replaceFields.title]: data[i][this.replaceFields.title],
|
||||
})
|
||||
if (data[i][this.replaceFields.children]) {
|
||||
generateList.call(this, data[i][this.replaceFields.children])
|
||||
@@ -32,7 +33,7 @@ function generateList(data) {
|
||||
}
|
||||
|
||||
function getParentKey(key, tree) {
|
||||
let parentKey;
|
||||
let parentKey
|
||||
for (let i = 0; i < tree.length; i++) {
|
||||
const node = tree[i]
|
||||
if (node[this.replaceFields.children]) {
|
||||
@@ -43,23 +44,26 @@ function getParentKey(key, tree) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return parentKey;
|
||||
return parentKey
|
||||
}
|
||||
|
||||
function renderTitle(nodeData) {
|
||||
const title = nodeData[this.replaceFields.title]
|
||||
if (this.state.searchValue && title.indexOf(this.state.searchValue) > -1) {
|
||||
return <>
|
||||
{title.substr(0, title.indexOf(this.state.searchValue))}
|
||||
<span style={{ color: '#f50' }}>{this.state.searchValue}</span>
|
||||
{title.substr(title.indexOf(this.state.searchValue) + this.state.searchValue.length)}
|
||||
</>
|
||||
return (
|
||||
<>
|
||||
{title.substr(0, title.indexOf(this.state.searchValue))}
|
||||
<span style={{ color: '#f50' }}>{this.state.searchValue}</span>
|
||||
{title.substr(
|
||||
title.indexOf(this.state.searchValue) + this.state.searchValue.length
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
return <>{title}</>
|
||||
}
|
||||
|
||||
function renderBreadcrumbItem() {
|
||||
|
||||
const path = ['顶级']
|
||||
|
||||
const findPath = (data, level) => {
|
||||
@@ -91,14 +95,16 @@ function renderBreadcrumbItem() {
|
||||
}
|
||||
|
||||
export default class QueryTreeLayout extends Component {
|
||||
|
||||
state = {
|
||||
loading: false,
|
||||
dataSource: [],
|
||||
expandedKeys: [],
|
||||
selectedKey: '',
|
||||
autoExpandParent: true,
|
||||
searchValue: ''
|
||||
searchValue: '',
|
||||
|
||||
collapsed: false,
|
||||
showSider: false,
|
||||
}
|
||||
|
||||
list = []
|
||||
@@ -108,16 +114,18 @@ export default class QueryTreeLayout extends Component {
|
||||
replaceFields = {
|
||||
value: 'id',
|
||||
title: 'title',
|
||||
children: 'children'
|
||||
children: 'children',
|
||||
}
|
||||
|
||||
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 () => { }
|
||||
this.loadData =
|
||||
typeof this.props.loadData === 'function' ? this.props.loadData : async () => {}
|
||||
|
||||
this.defaultExpanded = typeof this.props.defaultExpanded === 'boolean' ? this.props.defaultExpanded : false
|
||||
this.defaultExpanded =
|
||||
typeof this.props.defaultExpanded === 'boolean' ? this.props.defaultExpanded : false
|
||||
|
||||
if (this.props.replaceFields) {
|
||||
this.replaceFields = this.props.replaceFields
|
||||
@@ -131,6 +139,13 @@ export default class QueryTreeLayout extends Component {
|
||||
if (this.autoLoad) {
|
||||
this.onLoadData()
|
||||
}
|
||||
|
||||
window.addEventListener('resize', this.onResizeLayout)
|
||||
this.onResizeLayout()
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('resize', this.onResizeLayout)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,7 +166,7 @@ export default class QueryTreeLayout extends Component {
|
||||
}
|
||||
this.setState({
|
||||
dataSource: data,
|
||||
expandedKeys
|
||||
expandedKeys,
|
||||
})
|
||||
this.onLoaded()
|
||||
}
|
||||
@@ -162,8 +177,8 @@ export default class QueryTreeLayout extends Component {
|
||||
onLoading = () => {
|
||||
this.setState({
|
||||
loading: {
|
||||
indicator: <AntIcon type="loading" />
|
||||
}
|
||||
indicator: <AntIcon type="loading" />,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -178,28 +193,28 @@ export default class QueryTreeLayout extends Component {
|
||||
this.onLoadData()
|
||||
}
|
||||
|
||||
onExpand = (expandedKeys) => {
|
||||
onExpand = expandedKeys => {
|
||||
this.setState({
|
||||
expandedKeys,
|
||||
autoExpandParent: false
|
||||
autoExpandParent: false,
|
||||
})
|
||||
}
|
||||
|
||||
onSelect = (selectedKeys) => {
|
||||
onSelect = selectedKeys => {
|
||||
const selectedIds = []
|
||||
selectedKeys.forEach(p => {
|
||||
const data = this.list.find(m => m.key === p)
|
||||
selectedIds.push(data[this.replaceFields.value])
|
||||
})
|
||||
this.setState({
|
||||
selectedKey: selectedIds[0]
|
||||
selectedKey: selectedIds[0],
|
||||
})
|
||||
if (this.props.onSelect) {
|
||||
this.props.onSelect(selectedIds[0])
|
||||
}
|
||||
}
|
||||
|
||||
onSearch = (value) => {
|
||||
onSearch = value => {
|
||||
const expandedKeys = this.list
|
||||
.map(p => {
|
||||
if (p[this.replaceFields.title].indexOf(value) > -1) {
|
||||
@@ -212,34 +227,49 @@ export default class QueryTreeLayout extends Component {
|
||||
this.setState({
|
||||
expandedKeys,
|
||||
autoExpandParent: !!value,
|
||||
searchValue: value
|
||||
searchValue: value,
|
||||
})
|
||||
}
|
||||
|
||||
onResizeLayout = () => {
|
||||
this.setState({
|
||||
collapsed: window.innerWidth <= SIDER_BREAK_POINT,
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
const { dataSource, expandedKeys, autoExpandParent } = this.state
|
||||
const { loading, dataSource, expandedKeys, autoExpandParent, collapsed, showSider } =
|
||||
this.state
|
||||
|
||||
const props = {
|
||||
treeData: dataSource,
|
||||
expandedKeys,
|
||||
autoExpandParent
|
||||
autoExpandParent,
|
||||
}
|
||||
|
||||
const on = {
|
||||
onExpand: (expandedKeys) => this.onExpand(expandedKeys),
|
||||
onSelect: (selectedKeys) => this.onSelect(selectedKeys)
|
||||
onExpand: expandedKeys => this.onExpand(expandedKeys),
|
||||
onSelect: selectedKeys => this.onSelect(selectedKeys),
|
||||
}
|
||||
|
||||
return (
|
||||
<Layout className="yo-tree-layout">
|
||||
<Layout.Sider width="240px">
|
||||
<Layout.Sider
|
||||
width="240px"
|
||||
className={[
|
||||
collapsed ? 'yo-tree-layout--collapsed' : '',
|
||||
showSider ? 'open' : '',
|
||||
]
|
||||
.filter(p => p)
|
||||
.join(' ')}
|
||||
onMouseLeave={() => this.setState({ showSider: false })}
|
||||
>
|
||||
<Layout.Header>
|
||||
<div className="header-actions">
|
||||
<Input.Search
|
||||
allowClear={true}
|
||||
placeholder="请输入检索关键字"
|
||||
onSearch={(value) => this.onSearch(value)}
|
||||
onSearch={value => this.onSearch(value)}
|
||||
/>
|
||||
</div>
|
||||
</Layout.Header>
|
||||
@@ -248,37 +278,56 @@ export default class QueryTreeLayout extends Component {
|
||||
<AntIcon type="undo" onClick={() => this.onReloadData()} />
|
||||
</Tooltip>
|
||||
<Tooltip placement="bottom" title="折叠全部">
|
||||
<AntIcon type="switcher" onClick={() => this.setState({ expandedKeys: [] })} />
|
||||
<AntIcon
|
||||
type="switcher"
|
||||
onClick={() => this.setState({ expandedKeys: [] })}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className="yo-tree-layout--content">
|
||||
<Spin spinning={this.state.loading} indicator={<AntIcon type="loading" />} wrapperClassName="h-100-p">
|
||||
{
|
||||
!this.state.loading && !this.state.dataSource.length ?
|
||||
<Empty
|
||||
image={
|
||||
<div className="text-center pt-md">
|
||||
<AntIcon className="h3 mt-xl mb-md" type="smile" />
|
||||
<p>暂无数据</p>
|
||||
</div>
|
||||
}
|
||||
description={false}
|
||||
/>
|
||||
:
|
||||
<Tree
|
||||
{...props}
|
||||
{...on}
|
||||
titleRender={(nodeData) => renderTitle.call(this, nodeData)}
|
||||
/>
|
||||
}
|
||||
<Spin
|
||||
spinning={loading}
|
||||
indicator={<AntIcon type="loading" />}
|
||||
wrapperClassName="h-100-p"
|
||||
>
|
||||
{!loading && !dataSource.length ? (
|
||||
<Empty
|
||||
image={
|
||||
<div className="text-center pt-md">
|
||||
<AntIcon className="h3 mt-xl mb-md" type="smile" />
|
||||
<p>暂无数据</p>
|
||||
</div>
|
||||
}
|
||||
description={false}
|
||||
/>
|
||||
) : (
|
||||
<Tree
|
||||
{...props}
|
||||
{...on}
|
||||
titleRender={nodeData => renderTitle.call(this, nodeData)}
|
||||
/>
|
||||
)}
|
||||
</Spin>
|
||||
</div>
|
||||
</Layout.Sider>
|
||||
<Layout.Content>
|
||||
<Container mode="fluid">
|
||||
<Breadcrumb className="mt-md mb-md">
|
||||
{renderBreadcrumbItem.call(this)}
|
||||
</Breadcrumb>
|
||||
<Row gutter={16} align="middle">
|
||||
{collapsed && (
|
||||
<Col>
|
||||
<Button
|
||||
type="text"
|
||||
icon={<AntIcon type="menu" />}
|
||||
onClick={() => this.setState({ showSider: true })}
|
||||
/>
|
||||
</Col>
|
||||
)}
|
||||
<Col flex="1">
|
||||
<Breadcrumb className="mt-md mb-md">
|
||||
{renderBreadcrumbItem.call(this)}
|
||||
</Breadcrumb>
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
{this.props.children}
|
||||
</Layout.Content>
|
||||
|
||||
Reference in New Issue
Block a user