|
@@ -1,5 +1,5 @@
|
|
|
import React, { PureComponent, Fragment } from 'react';
|
|
|
-import { Alert, List, Select, Input, Checkbox, Button, Icon, Pagination } from 'antd';
|
|
|
+import { Alert, List, Select, Input, Checkbox, Button, Pagination } from 'antd';
|
|
|
import PropTypes from 'prop-types';
|
|
|
import Authorized from '../../utils/Authorized';
|
|
|
import styles from './StandardCardList.less';
|
|
@@ -7,48 +7,27 @@ import styles from './StandardCardList.less';
|
|
|
function generator(props) {
|
|
|
return (WrappedComponent) => {
|
|
|
return (
|
|
|
- <WrappedComponent {...props}/>
|
|
|
+ <WrappedComponent {...props} />
|
|
|
);
|
|
|
- }
|
|
|
+ };
|
|
|
}
|
|
|
function getSearchField(options) {
|
|
|
if (options && options.keys && options.keys.length) {
|
|
|
return options.keys[0].field;
|
|
|
- } else {
|
|
|
- return;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
class StandardCardList extends PureComponent {
|
|
|
- constructor(props) {
|
|
|
- super(props);
|
|
|
- const {
|
|
|
- keepUIState,
|
|
|
- header: {
|
|
|
- basicSearch,
|
|
|
- }
|
|
|
- } = this.props;
|
|
|
- this.state = {
|
|
|
- batchActionKey: keepUIState.batchActionKey,
|
|
|
- isAdvancedLevel: keepUIState.isAdvancedLevel || false,
|
|
|
- searchSelectKey: keepUIState.searchSelectKey || getSearchField(basicSearch),
|
|
|
- searchInputValue: keepUIState.searchInputValue || '',
|
|
|
- selectedKeys: keepUIState.selectedKeys || [],
|
|
|
- allChecked: keepUIState.allChecked || false,
|
|
|
- selectedStatusKey: keepUIState.selectedStatusKey || 'ALL',
|
|
|
- pageNo: keepUIState.pageNo || 1,
|
|
|
- pageSize: keepUIState.pageSize || 15,
|
|
|
- totalSize: keepUIState.totalSize || 0,
|
|
|
- }
|
|
|
- }
|
|
|
static defaultProps = {
|
|
|
loading: false,
|
|
|
dataSource: [],
|
|
|
+ header: false,
|
|
|
+ footer: false,
|
|
|
}
|
|
|
static propTypes = {
|
|
|
loading: PropTypes.bool,
|
|
|
dataSource: PropTypes.array,
|
|
|
- component: PropTypes.func,
|
|
|
+ component: PropTypes.func.isRequired,
|
|
|
header: PropTypes.oneOfType([
|
|
|
PropTypes.object,
|
|
|
PropTypes.bool,
|
|
@@ -58,6 +37,30 @@ class StandardCardList extends PureComponent {
|
|
|
PropTypes.bool,
|
|
|
]),
|
|
|
}
|
|
|
+ constructor(props) {
|
|
|
+ super(props);
|
|
|
+ const {
|
|
|
+ keepUIState,
|
|
|
+ header: {
|
|
|
+ basicSearch,
|
|
|
+ },
|
|
|
+ footer: {
|
|
|
+ pagination,
|
|
|
+ },
|
|
|
+ } = this.props;
|
|
|
+ this.state = {
|
|
|
+ batchActionKey: keepUIState.batchActionKey,
|
|
|
+ isAdvancedLevel: keepUIState.isAdvancedLevel || false,
|
|
|
+ searchSelectKey: keepUIState.searchSelectKey || getSearchField(basicSearch),
|
|
|
+ searchInputValue: keepUIState.searchInputValue || '',
|
|
|
+ selectedKeys: keepUIState.selectedKeys || [],
|
|
|
+ allChecked: keepUIState.allChecked || false,
|
|
|
+ selectedStatusKey: keepUIState.selectedStatusKey || 'ALL',
|
|
|
+ pageNo: keepUIState.pageNo || pagination.pageNo || 1,
|
|
|
+ pageSize: keepUIState.pageSize || pagination.pageSize || 15,
|
|
|
+ totalSize: keepUIState.totalSize || pagination.totalSize || 0,
|
|
|
+ };
|
|
|
+ }
|
|
|
componentWillReceiveProps(nextProps) {
|
|
|
if (nextProps.footer) {
|
|
|
const { pagination } = nextProps.footer;
|
|
@@ -65,11 +68,142 @@ class StandardCardList extends PureComponent {
|
|
|
this.setState({ pageNo, pageSize, totalSize });
|
|
|
}
|
|
|
}
|
|
|
- //过滤
|
|
|
+ getListHeader = () => {
|
|
|
+ const {
|
|
|
+ header: { basicSearch, advancedSearch, onCreateClick },
|
|
|
+ footer: { pagination },
|
|
|
+ } = this.props;
|
|
|
+ const { keys } = basicSearch;
|
|
|
+ return (
|
|
|
+ <div className={styles.header}>
|
|
|
+ <div className={styles.headerSearch}>
|
|
|
+ <div className={styles.basicSearch}>
|
|
|
+ <div className={styles.left}>
|
|
|
+ <Select
|
|
|
+ onChange={this.handleStatusChange}
|
|
|
+ value={this.state.selectedStatusKey}
|
|
|
+ style={{ width: '20%', marginRight: 10 }}
|
|
|
+ >
|
|
|
+ <Select.Option key="all" value="ALL">全部状态</Select.Option>
|
|
|
+ <Select.Option key="normal" value="NORMAL">正常</Select.Option>
|
|
|
+ <Select.Option key="delete" value="DELETE">已删除</Select.Option>
|
|
|
+ </Select>
|
|
|
+ <Input.Search
|
|
|
+ value={this.state.searchInputValue}
|
|
|
+ style={{ width: '75%' }}
|
|
|
+ addonBefore={
|
|
|
+ <Select
|
|
|
+ placeholder="请选择"
|
|
|
+ value={this.state.searchSelectKey}
|
|
|
+ onChange={this.handleSearchSelectChange}
|
|
|
+ >
|
|
|
+ {keys.map(item => (
|
|
|
+ <Select.Option
|
|
|
+ key={item.field}
|
|
|
+ value={item.field}
|
|
|
+ >
|
|
|
+ {item.name}
|
|
|
+ </Select.Option>))}
|
|
|
+ </Select>
|
|
|
+ }
|
|
|
+ placeholder="请输入"
|
|
|
+ enterButton
|
|
|
+ onChange={this.handleInputChange}
|
|
|
+ onSearch={this.handleSearchBtnClick}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div className={styles.right}>
|
|
|
+ {advancedSearch &&
|
|
|
+ (this.state.isAdvancedLevel ? <a>普通搜索</a> : <a>高级搜索</a>)
|
|
|
+ }
|
|
|
+ <Button icon="sync" onClick={this.handleRefreshBtnClick}>刷新</Button>
|
|
|
+ <Authorized authority="root" noMatch={null}>
|
|
|
+ <Button
|
|
|
+ icon="plus"
|
|
|
+ type="primary"
|
|
|
+ style={{ marginLeft: 5 }}
|
|
|
+ onClick={onCreateClick}
|
|
|
+ >新建
|
|
|
+ </Button>
|
|
|
+ </Authorized>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ {advancedSearch &&
|
|
|
+ this.state.isAdvancedLevel ?
|
|
|
+ <div className={styles.advancedSearch}>{advancedSearch}</div>
|
|
|
+ : null
|
|
|
+ }
|
|
|
+ </div>
|
|
|
+ <Alert
|
|
|
+ message={(
|
|
|
+ <Fragment>
|
|
|
+ 已选择 <a style={{ fontWeight: 600 }}>{this.state.selectedKeys.length}</a> 项
|
|
|
+ 总计 <a style={{ fontWeight: 600 }}>{pagination.totalSize}</a> 项
|
|
|
+ <a onClick={this.cleanSelectedKeys} style={{ fontWeight: 600 }}>清空</a>
|
|
|
+ </Fragment>
|
|
|
+ )}
|
|
|
+ type="info"
|
|
|
+ showIcon
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+ getListFooter = () => {
|
|
|
+ const { footer: { batchActions, pagination } } = this.props;
|
|
|
+ const paginationProps = {
|
|
|
+ total: this.state.totalSize,
|
|
|
+ current: this.state.pageNo,
|
|
|
+ pageSize: this.state.pageSize,
|
|
|
+ showSizeChanger: true,
|
|
|
+ showQuickJumper: true,
|
|
|
+ onChange: this.handleListPageChange,
|
|
|
+ onShowSizeChange: this.handleListPageSizeChange,
|
|
|
+ };
|
|
|
+ return (
|
|
|
+ <div className={styles.footer}>
|
|
|
+ {batchActions && (
|
|
|
+ <Authorized authority="root" noMatch={null}>
|
|
|
+ <div className={styles.batch}>
|
|
|
+ <Checkbox
|
|
|
+ checked={this.state.allChecked}
|
|
|
+ onChange={this.handleAllSelectChange}
|
|
|
+ >全选
|
|
|
+ </Checkbox>
|
|
|
+ <Select
|
|
|
+ style={{ width: 100 }}
|
|
|
+ placeholder="请选择..."
|
|
|
+ value={this.state.batchActionKey}
|
|
|
+ onChange={this.handleBatchActionSelectChange}
|
|
|
+ >
|
|
|
+ {batchActions.map(item => (
|
|
|
+ <Select.Option key={item.key} value={item.key}>
|
|
|
+ {item.name}
|
|
|
+ </Select.Option>))}
|
|
|
+ </Select>
|
|
|
+ <Button
|
|
|
+ type="primary"
|
|
|
+ style={{ marginLeft: 15 }}
|
|
|
+ onClick={this.handleBatchBtnClick}
|
|
|
+ disabled={!this.state.selectedKeys.length}
|
|
|
+ >确定
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ </Authorized>)}
|
|
|
+ {pagination && (
|
|
|
+ <div className={styles.pagination}>
|
|
|
+ <Pagination
|
|
|
+ {...paginationProps}
|
|
|
+ showTotal={total => `共 ${total} 条`}
|
|
|
+ />
|
|
|
+ </div>)}
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+ // 过滤
|
|
|
handleFilterOperation = (kv) => {
|
|
|
const {
|
|
|
header: {
|
|
|
- onFilterClick
|
|
|
+ onFilterClick,
|
|
|
},
|
|
|
} = this.props;
|
|
|
const {
|
|
@@ -79,7 +213,7 @@ class StandardCardList extends PureComponent {
|
|
|
pageNo,
|
|
|
pageSize,
|
|
|
} = this.state;
|
|
|
- let queryParams = {
|
|
|
+ const queryParams = {
|
|
|
pageNo,
|
|
|
pageSize,
|
|
|
[searchSelectKey]: searchInputValue,
|
|
@@ -91,7 +225,7 @@ class StandardCardList extends PureComponent {
|
|
|
}
|
|
|
onFilterClick(queryParams, this.state);
|
|
|
}
|
|
|
- //单选/取消单选
|
|
|
+ // 单选/取消单选
|
|
|
handleItemSelectChange = (itemId, checked) => {
|
|
|
const { selectedKeys } = this.state;
|
|
|
const newSelectedKeys = [...selectedKeys];
|
|
@@ -101,7 +235,7 @@ class StandardCardList extends PureComponent {
|
|
|
this.setState({ selectedKeys: newSelectedKeys.filter(a => a !== itemId) });
|
|
|
}
|
|
|
}
|
|
|
- //全选/取消全选
|
|
|
+ // 全选/取消全选
|
|
|
handleAllSelectChange = (e) => {
|
|
|
const { dataSource } = this.props;
|
|
|
let newSelectedKeys = [];
|
|
@@ -113,14 +247,14 @@ class StandardCardList extends PureComponent {
|
|
|
selectedKeys: newSelectedKeys,
|
|
|
});
|
|
|
}
|
|
|
- //取消全选
|
|
|
+ // 取消全选
|
|
|
cleanSelectedKeys = () => {
|
|
|
this.setState({
|
|
|
selectedKeys: [],
|
|
|
allChecked: false,
|
|
|
});
|
|
|
}
|
|
|
- //刷新页面,重置筛选参数
|
|
|
+ // 刷新页面,重置筛选参数
|
|
|
cleanFilterParams = () => {
|
|
|
const { header: { basicSearch } } = this.props;
|
|
|
this.setState({
|
|
@@ -133,36 +267,36 @@ class StandardCardList extends PureComponent {
|
|
|
selectedStatusKey: 'ALL',
|
|
|
});
|
|
|
}
|
|
|
- //过滤状态
|
|
|
+ // 过滤状态
|
|
|
handleStatusChange = (value) => {
|
|
|
this.setState({
|
|
|
- selectedStatusKey: value,
|
|
|
+ selectedStatusKey: value,
|
|
|
}, () =>
|
|
|
this.handleFilterOperation({ status: value })
|
|
|
);
|
|
|
}
|
|
|
- //选择搜索字段
|
|
|
+ // 选择搜索字段
|
|
|
handleSearchSelectChange = (value) => {
|
|
|
this.setState({ searchSelectKey: value });
|
|
|
}
|
|
|
- //响应input输入
|
|
|
+ // 响应input输入
|
|
|
handleInputChange = (e) => {
|
|
|
this.setState({ searchInputValue: e.target.value });
|
|
|
}
|
|
|
- //筛选搜索操作
|
|
|
+ // 筛选搜索操作
|
|
|
handleSearchBtnClick = (value) => {
|
|
|
const { searchSelectKey } = this.state;
|
|
|
this.setState({
|
|
|
- searchInputValue: value,
|
|
|
+ searchInputValue: value,
|
|
|
}, () =>
|
|
|
this.handleFilterOperation({ [searchSelectKey]: value })
|
|
|
);
|
|
|
}
|
|
|
- //刷新操作
|
|
|
+ // 刷新操作
|
|
|
handleRefreshBtnClick = () => {
|
|
|
this.handleFilterOperation({});
|
|
|
}
|
|
|
- //list pageNo变化
|
|
|
+ // list pageNo变化
|
|
|
handleListPageChange = (page, pageSize) => {
|
|
|
this.setState({
|
|
|
pageSize,
|
|
@@ -174,7 +308,7 @@ class StandardCardList extends PureComponent {
|
|
|
});
|
|
|
});
|
|
|
}
|
|
|
- //list pageSize变化
|
|
|
+ // list pageSize变化
|
|
|
handleListPageSizeChange = (current, size) => {
|
|
|
this.setState({
|
|
|
pageSize: size,
|
|
@@ -186,152 +320,16 @@ class StandardCardList extends PureComponent {
|
|
|
});
|
|
|
});
|
|
|
}
|
|
|
- //选择批量处理类型
|
|
|
+ // 选择批量处理类型
|
|
|
handleBatchActionSelectChange = (value) => {
|
|
|
this.setState({ batchActionKey: value });
|
|
|
}
|
|
|
- //批量处理操作
|
|
|
+ // 批量处理操作
|
|
|
handleBatchBtnClick = () => {
|
|
|
const { footer: { onBatchClick } } = this.props;
|
|
|
const { batchActionKey, selectedKeys } = this.state;
|
|
|
onBatchClick(batchActionKey, selectedKeys);
|
|
|
}
|
|
|
- getListHeader = () => {
|
|
|
- const {
|
|
|
- header: { basicSearch, advancedSearch, onCreateClick },
|
|
|
- footer: { pagination },
|
|
|
- } = this.props;
|
|
|
- const { keys, value } = basicSearch;
|
|
|
- return (
|
|
|
- <div className={styles.header}>
|
|
|
- <div className={styles.headerSearch}>
|
|
|
- <div className={styles.basicSearch}>
|
|
|
- <div className={styles.left}>
|
|
|
- <Select
|
|
|
- onChange={this.handleStatusChange}
|
|
|
- value={this.state.selectedStatusKey}
|
|
|
- style={{ width: '20%', marginRight: 10 }}
|
|
|
- >
|
|
|
- <Select.Option key="all" value="ALL">全部状态</Select.Option>
|
|
|
- <Select.Option key="normal" value="NORMAL">正常</Select.Option>
|
|
|
- <Select.Option key="delete" value="DELETE">已删除</Select.Option>
|
|
|
- </Select>
|
|
|
- <Input.Search
|
|
|
- value={this.state.searchInputValue}
|
|
|
- style={{ width: '75%' }}
|
|
|
- addonBefore={
|
|
|
- <Select
|
|
|
- placeholder="请选择"
|
|
|
- value={this.state.searchSelectKey}
|
|
|
- onChange={this.handleSearchSelectChange}
|
|
|
- >
|
|
|
- {keys.map(item =>
|
|
|
- <Select.Option
|
|
|
- key={item.field}
|
|
|
- value={item.field}
|
|
|
- >
|
|
|
- {item.name}
|
|
|
- </Select.Option>
|
|
|
- )}
|
|
|
- </Select>
|
|
|
- }
|
|
|
- placeholder="请输入"
|
|
|
- enterButton
|
|
|
- onChange={this.handleInputChange}
|
|
|
- onSearch={this.handleSearchBtnClick}
|
|
|
- />
|
|
|
- </div>
|
|
|
- <div className={styles.right}>
|
|
|
- {advancedSearch &&
|
|
|
- (this.state.isAdvancedLevel ? <a>普通搜索</a> : <a>高级搜索</a>)
|
|
|
- }
|
|
|
- <Button icon="sync" onClick={this.handleRefreshBtnClick}>刷新</Button>
|
|
|
- <Authorized authority="root" noMatch={null}>
|
|
|
- <Button
|
|
|
- icon="plus"
|
|
|
- type="primary"
|
|
|
- style={{ marginLeft: 5 }}
|
|
|
- onClick={onCreateClick}
|
|
|
- >新建
|
|
|
- </Button>
|
|
|
- </Authorized>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- {advancedSearch &&
|
|
|
- this.state.isAdvancedLevel ?
|
|
|
- <div className={styles.advancedSearch}>{advancedSearch}</div>
|
|
|
- : null
|
|
|
- }
|
|
|
- </div>
|
|
|
- <Alert
|
|
|
- message={(
|
|
|
- <Fragment>
|
|
|
- 已选择 <a style={{ fontWeight: 600 }}>{this.state.selectedKeys.length}</a> 项
|
|
|
- 总计 <a style={{ fontWeight: 600 }}>{pagination.totalSize}</a> 项
|
|
|
- <a onClick={this.cleanSelectedKeys} style={{ fontWeight: 600 }}>清空</a>
|
|
|
- </Fragment>
|
|
|
- )}
|
|
|
- type="info"
|
|
|
- showIcon
|
|
|
- />
|
|
|
- </div>
|
|
|
- );
|
|
|
- }
|
|
|
- getListFooter = () => {
|
|
|
- const { footer: { batchActions, pagination } } = this.props;
|
|
|
- const paginationProps = {
|
|
|
- total: this.state.totalSize,
|
|
|
- current: this.state.pageNo,
|
|
|
- pageSize: this.state.pageSize,
|
|
|
- showSizeChanger: true,
|
|
|
- showQuickJumper: true,
|
|
|
- onChange: this.handleListPageChange,
|
|
|
- onShowSizeChange: this.handleListPageSizeChange,
|
|
|
- ...pagination,
|
|
|
- };
|
|
|
- return (
|
|
|
- <div className={styles.footer}>
|
|
|
- {batchActions &&
|
|
|
- <Authorized authority="root" noMatch={null}>
|
|
|
- <div className={styles.batch}>
|
|
|
- <Checkbox
|
|
|
- checked={this.state.allChecked}
|
|
|
- onChange={this.handleAllSelectChange}
|
|
|
- >全选
|
|
|
- </Checkbox>
|
|
|
- <Select
|
|
|
- style={{ width: 100 }}
|
|
|
- placeholder="请选择..."
|
|
|
- value={this.state.batchActionKey}
|
|
|
- onChange={this.handleBatchActionSelectChange}
|
|
|
- >
|
|
|
- {batchActions.map((item) =>
|
|
|
- <Select.Option key={item.key} value={item.key}>
|
|
|
- {item.name}
|
|
|
- </Select.Option>
|
|
|
- )}
|
|
|
- </Select>
|
|
|
- <Button
|
|
|
- type="primary"
|
|
|
- style={{ marginLeft: 15 }}
|
|
|
- onClick={this.handleBatchBtnClick}
|
|
|
- disabled={this.state.selectedKeys.length ? false : true}
|
|
|
- >确定
|
|
|
- </Button>
|
|
|
- </div>
|
|
|
- </Authorized>
|
|
|
- }
|
|
|
- {pagination &&
|
|
|
- <div className={styles.pagination}>
|
|
|
- <Pagination
|
|
|
- {...paginationProps}
|
|
|
- showTotal={(total) => `共 ${total} 条`}
|
|
|
- />
|
|
|
- </div>
|
|
|
- }
|
|
|
- </div>
|
|
|
- );
|
|
|
- }
|
|
|
render() {
|
|
|
const { selectedKeys } = this.state;
|
|
|
const { component, dataSource, loading, header, footer, grid, onDelete } = this.props;
|
|
@@ -339,6 +337,7 @@ class StandardCardList extends PureComponent {
|
|
|
const listHeader = header ? this.getListHeader() : false;
|
|
|
return (
|
|
|
<List
|
|
|
+ className={styles.list}
|
|
|
grid={grid}
|
|
|
bordered={false}
|
|
|
split={false}
|
|
@@ -350,7 +349,7 @@ class StandardCardList extends PureComponent {
|
|
|
<List.Item>
|
|
|
{generator({
|
|
|
onDelete,
|
|
|
- selected: -1 === selectedKeys.indexOf(item.id) ? false : true,
|
|
|
+ selected: selectedKeys.indexOf(item.id) !== -1,
|
|
|
onSelectChange: this.handleItemSelectChange,
|
|
|
...item,
|
|
|
})(component)}
|