| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594 |
- import React from 'react';
- import { Table, Switch, ButtonGroup, Button, Avatar } from '@douyinfe/semi-ui';
- import * as dateFns from 'date-fns';
- const DAY = 24 * 60 * 60 * 1000;
- const figmaIconUrl = 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/figma-icon.png';
- class App extends React.Component {
- constructor(props) {
- super(props);
- const dataTotalSize = 46;
- const columns = [
- {
- title: '标题',
- dataIndex: 'name',
- width: 400,
- render: (text, record, index) => {
- return (
- <div>
- <Avatar size="small" shape="square" src={figmaIconUrl} style={{ marginRight: 12 }}></Avatar>
- {text}
- </div>
- );
- },
- filters: [
- {
- text: 'Semi Design 设计稿',
- value: 'Semi Design 设计稿',
- },
- {
- text: 'Semi Pro 设计稿',
- value: 'Semi Pro 设计稿',
- },
- ],
- onFilter: (value, record) => record.name.includes(value),
- },
- {
- title: '大小',
- dataIndex: 'size',
- sorter: (a, b) => a.size - b.size > 0 ? 1 : -1,
- render: (text) => `${text} KB`
- },
- {
- title: '所有者',
- dataIndex: 'owner',
- render: (text, record, index) => {
- return (
- <div>
- <Avatar size="small" color={record.avatarBg} style={{ marginRight: 4 }}>{typeof text === 'string' && text.slice(0, 1)}</Avatar>
- {text}
- </div>
- );
- }
-
- },
- {
- title: '更新日期',
- dataIndex: 'updateTime',
- sorter: (a, b) => a.updateTime - b.updateTime > 0 ? 1 : -1,
- render: (value) => {
- return dateFns.format(new Date(value), 'yyyy-MM-dd');
- }
- }
- ];
- this.getData = () => {
- const data = [];
- for (let i = 0; i < dataTotalSize; i++) {
- const isSemiDesign = i % 2 === 0;
- const randomNumber = (i * 1000) % 199;
- data.push({
- key: '' + i,
- name: isSemiDesign ? `Semi Design 设计稿${i}.fig` : `Semi Pro 设计稿${i}.fig`,
- owner: isSemiDesign ? '姜鹏志' : '郝宣',
- size: randomNumber,
- updateTime: new Date().valueOf() + randomNumber * DAY,
- avatarBg: isSemiDesign ? 'grey' : 'red'
- });
- }
- return data;
- };
- const data = this.getData();
- this.data = data;
- this.mergeColumns = (column, columns, keys = ['dataIndex']) => {
- columns = [...columns];
- columns.forEach((curColumn, index) => {
- let isTarget = !!(keys && keys.length);
- for (let key of keys) {
- if (column[key] !== curColumn[key]) {
- isTarget = false;
- break;
- }
- }
- if (isTarget) {
- columns[index] = { ...curColumn, ...column };
- }
- });
- return columns;
- };
- this.filterData = (filters, dataSource) => {
- dataSource = [...dataSource];
- filters.forEach(filter => {
- let filteredValue = filter.filteredValue;
- let dataIndex = filter.dataIndex;
- if (Array.isArray(filteredValue) && filteredValue.length && dataIndex) {
- dataSource = dataSource.filter(
- data => filteredValue.filter(value => String(data[dataIndex]).indexOf(value) > -1).length
- );
- }
- });
- return dataSource;
- };
- this.getSelfSorterColumn = columns => {
- columns = columns || this.state.columns;
- return columns.filter(column => !!column.sorter)[0];
- };
- this.getSelfFilterColumns = columns => {
- columns = columns || this.state.columns;
- return columns.filter(column => Array.isArray(column.filteredValue) && column.filteredValue.length);
- };
- this.sortData = (sortObj, dataSource) => {
- let { sorter, sortOrder, dataIndex } = sortObj;
- if (sorter && sortOrder && typeof sorter !== 'function') {
- sorter = (a, b) => (a[dataIndex] > b[dataIndex] ? 1 : -1);
- }
- if (typeof sorter === 'function') {
- dataSource = [...dataSource].sort(sorter);
- if (sortOrder === 'descend') {
- dataSource = dataSource.reverse();
- }
- }
- return dataSource;
- };
- this.fetchData = (currentPage = 1, sorter = {}, filters = []) => {
- // console.log(`FetchData currentPage: `, currentPage);
- let pagination = { ...this.state.pagination, currentPage };
- return new Promise((res, rej) => {
- setTimeout(() => {
- let data = [...this.data];
- data = this.sortData(sorter, data);
- data = this.filterData(filters, data);
- let dataSource = data.slice(
- (currentPage - 1) * pagination.pageSize,
- currentPage * pagination.pageSize
- );
- pagination.total = data.length;
- res({
- dataSource,
- pagination,
- sorter,
- filters,
- });
- }, 1500);
- });
- };
- this.setPage = (currentPage, sorter, filters) => {
- if (this.state.loading) {
- return;
- }
- if (typeof currentPage !== 'number') {
- currentPage = (this.state.pagination && this.state.pagination.currentPage) || 1;
- }
- sorter = sorter || this.getSelfSorterColumn();
- filters = filters || this.getSelfFilterColumns();
- this.setState({ loading: true });
- this.fetchData(currentPage, sorter, filters)
- .then(({ dataSource, pagination, sorter, filters }) => {
- let columns = [...this.state.columns];
- columns = this.mergeColumns(sorter, columns);
- for (let filterObj of filters) {
- columns = this.mergeColumns(filterObj, columns);
- }
- this.setState({
- loading: false,
- pagination,
- dataSource,
- columns,
- });
- })
- .catch(err => {
- console.error(err);
- this.setState({ loading: false });
- });
- };
- this.toggleFixHeader = checked => {
- let scroll = { ...this.state.scroll };
- if (checked) {
- scroll.y = 300;
- } else {
- scroll.y = null;
- }
- this.setState({ scroll });
- };
- this.toggleFixColumns = checked => {
- let columns = [...this.state.columns];
- let scroll = { ...this.state.scroll };
- let expandCellFixed = this.state.expandCellFixed;
- let rowSelection = this.state.rowSelection;
- if (checked) {
- columns[0].fixed = true;
- if (rowSelection) {
- rowSelection = { ...rowSelection, fixed: true };
- }
- if (columns.length > 1) {
- columns[columns.length - 1].fixed = 'right';
- }
- scroll.x = '150%';
- expandCellFixed = true;
- } else {
- columns.forEach(column => {
- column.fixed = false;
- });
- scroll.x = null;
- expandCellFixed = false;
- if (rowSelection) {
- rowSelection = { ...rowSelection, fixed: false };
- }
- }
- this.setState({
- rowSelection,
- expandCellFixed,
- columns,
- scroll,
- });
- };
- this.toggleRowSelection = checked => {
- let rowSelection = this.state.rowSelection;
- // const anyColumnFixed = this.state.columns.some(column => !!column.fixed);
- if (checked) {
- rowSelection = {
- width: 48,
- fixed: true,
- onChange: (selectedRowKeys, selectedRows) =>
- console.log(
- 'Selection changed, selectedRowKeys: ',
- selectedRowKeys,
- 'selectedRows: ',
- selectedRows
- ),
- };
- } else {
- rowSelection = null;
- }
- this.setState({ rowSelection });
- };
- this.toggleLoading = checked => {
- let loading = this.state.loading;
- if (checked) {
- loading = true;
- } else {
- loading = false;
- }
- this.setState({ loading });
- };
- this.toggleExpandedRowRender = checked => {
- let expandedRowRender = this.state.expandedRowRender;
- if (checked) {
- expandedRowRender = record => {
- return {
- children: <p>{record.description}</p>,
- fixed: 'left',
- };
- };
- } else {
- expandedRowRender = null;
- }
- this.setState({ expandedRowRender });
- };
- this.toggleShowSorter = checked => {
- let columns = [...this.state.columns];
- if (checked) {
- columns.forEach(column => column.dataIndex === 'age' && (column.sorter = true));
- } else {
- columns.forEach(column => (column.sorter = null));
- }
- this.setState({ columns });
- };
- this.toggleShowFilter = checked => {
- let columns = [...this.state.columns];
- if (checked) {
- columns.forEach(column => {
- if (column.dataIndex === 'name') {
- column.filters = [
- {
- text: '姓名中包含 1',
- value: '1',
- },
- {
- text: '姓名中包含 2',
- value: '2',
- },
- {
- text: '姓名中包含 3',
- value: '3',
- },
- ];
- column.filteredValue = [];
- }
- });
- } else {
- columns.forEach(column => {
- column.filters = null;
- column.filteredValue = null;
- });
- }
- this.setState({ columns });
- if (!checked) {
- this.setPage(null, null, []);
- }
- };
- this.onChange = (data = {}) => {
- console.log('Table changed: ', data);
- let { pagination, sorter, filters } = data;
- this.setPage(pagination.currentPage, sorter, filters);
- };
- this.onExpandedRowsChange = rows => {
- console.log('Expanded rows changed to: ', rows);
- const expandedRowKeys = (Array.isArray(rows) && rows.map(row => row.key)) || [];
- this.setState({ expandedRowKeys });
- };
- this.toggleExpandedRowKeys = checked => {
- let expandedRowKeys = [];
- if (checked) {
- let dataSource = [...this.state.dataSource];
- expandedRowKeys.push(
- ...dataSource.reduce((arr, data) => {
- if (data.key) {
- arr.push(data.key);
- }
- return arr;
- }, [])
- );
- this.toggleExpandedRowRender(true);
- }
- this.setState({ expandedRowKeys });
- };
- this.toggleBordered = checked => {
- let bordered = false;
- if (checked) {
- bordered = true;
- }
- this.setState({ bordered });
- };
- this.toggleResizable = checked => {
- let resizable = !!checked || false;
- this.setState({ resizable, bordered: resizable });
- };
- this.toggleHideHeader = checked => {
- let showHeader = true;
- if (checked) {
- showHeader = false;
- }
- this.setState({ showHeader });
- };
- this.toggleFooter = checked => {
- const footer = checked ? dataSource => <p style={{ margin: 0 }}>This is footer.</p> : null;
- this.setState({ footer });
- };
- this.toggleTitle = checked => {
- const title = checked ? 'This is title.' : null;
- this.setState({ title });
- };
- this.toggleHidePagination = checked => {
- let pagination = checked
- ? false
- : {
- currentPage: 1,
- pageSize: 8,
- total: data.length,
- onPageChange: page => this.setPage(page),
- };
- this.setState({ pagination });
- };
- this.toggleDataSource = checked => {
- if (checked) {
- this.setState({ dataSource: [] });
- } else {
- this.setPage();
- }
- };
- this.switchPagination = position => {
- let pagination = this.state.pagination;
- const defaultPagination = {
- currentPage: 1,
- pageSize: 8,
- total: data.length,
- onPageChange: page => this.setPage(page),
- };
- const positions = ['bottom', 'top', 'both'];
- if (position === true || position === false) {
- pagination = position ? { ...defaultPagination, ...pagination } : false;
- } else if (positions.includes(position)) {
- pagination = { ...defaultPagination, ...pagination, position };
- }
- this.setState({ pagination });
- };
- this.state = {
- loading: false,
- columns,
- scroll: {},
- rowSelection: null,
- expandedRowRender: null,
- expandCellFixed: false,
- defaultExpandedRowKeys: [],
- title: null,
- footer: null,
- expandedRowKeys: [],
- showHeader: true,
- resizable: false,
- pagination: {
- currentPage: 1,
- pageSize: 8,
- total: data.length,
- onPageChange: page => this.setPage(page),
- },
- dataSource: [],
- };
- this.TableSwitch = function TableSwitch({
- text,
- children,
- checked,
- onChange,
- style = { display: 'inline-flex', alignItems: 'center', margin: 5 },
- }) {
- const switchProps = { onChange };
- if (checked != null) {
- switchProps.checked = !!checked;
- }
- return (
- <span style={style}>
- <span>{text}</span>
- {children != null ? children : <Switch size="small" {...switchProps} />}
- </span>
- );
- };
- }
- componentDidMount() {
- this.setPage(1);
- }
- render() {
- let {
- columns,
- dataSource,
- pagination,
- loading,
- scroll,
- rowSelection,
- expandedRowRender,
- expandCellFixed,
- expandedRowKeys,
- bordered,
- resizable,
- title,
- footer,
- showHeader,
- defaultExpandedRowKeys,
- } = this.state;
- const wrapStyle = { marginBottom: 15, display: 'flex', justifyContent: 'space-around', flexWrap: 'wrap' };
- const TableSwitch = this.TableSwitch;
- return (
- <div>
- <div style={wrapStyle}>
- <TableSwitch text="固定表头:" checked={scroll && scroll.y} onChange={this.toggleFixHeader} />
- <TableSwitch text="隐藏表头:" onChange={this.toggleHideHeader} />
- <TableSwitch text="显示标题:" onChange={this.toggleTitle} />
- <TableSwitch text="显示底部:" onChange={this.toggleFooter} />
- <TableSwitch text="固定列:" onChange={this.toggleFixColumns} />
- <TableSwitch text="显示选择列:" onChange={this.toggleRowSelection} />
- <TableSwitch text="显示加载状态:" onChange={this.toggleLoading} checked={loading} />
- <TableSwitch
- text="无数据:"
- onChange={this.toggleDataSource}
- checked={!dataSource || !dataSource.length}
- />
- <TableSwitch text="开启排序功能:" onChange={this.toggleShowSorter} />
- <TableSwitch text="开启过滤功能:" onChange={this.toggleShowFilter} />
- <TableSwitch
- text="开启行展开功能:"
- onChange={this.toggleExpandedRowRender}
- checked={typeof expandedRowRender === 'function'}
- />
- <TableSwitch text="展开当前所有行:" onChange={this.toggleExpandedRowKeys} />
- <TableSwitch text="显示边框:" onChange={this.toggleBordered} checked={bordered} />
- <TableSwitch text="开启列伸缩功能:" onChange={this.toggleResizable} />
- <TableSwitch text="分页控件:">
- <ButtonGroup>
- <Button onClick={() => this.switchPagination('bottom')}>Bottom</Button>
- <Button onClick={() => this.switchPagination('top')}>Top</Button>
- <Button onClick={() => this.switchPagination('both')}>Both</Button>
- <Button onClick={() => this.switchPagination(false)}>None</Button>
- </ButtonGroup>
- </TableSwitch>
- </div>
- <Table
- defaultExpandedRowKeys={defaultExpandedRowKeys}
- onExpandedRowsChange={this.onExpandedRowsChange}
- title={title}
- footer={footer}
- showHeader={showHeader}
- bordered={bordered}
- onChange={this.onChange}
- expandCellFixed={expandCellFixed}
- expandedRowRender={expandedRowRender}
- expandedRowKeys={expandedRowKeys}
- rowSelection={rowSelection}
- scroll={scroll}
- columns={columns}
- dataSource={dataSource}
- pagination={pagination}
- loading={loading}
- resizable={resizable}
- />
- </div>
- );
- }
- }
- render(App);
|