美文网首页
Ant Design Pro 学习之table使用

Ant Design Pro 学习之table使用

作者: 小马将过河 | 来源:发表于2019-04-24 14:39 被阅读0次

在table的行render时常用的操作

1、时间格式化,指定时区

 {

​      title: '更新时间',

​      dataIndex: 'updateTime',

​      sorter: true,

​      render: val => <span>{moment(val).utc().format('YYYY-MM-DD HH:mm:ss')}</span>,

​    },

2、列表上显示图片

    {
      title: '肺功能报告',
      dataIndex: 'url',
      render: text => <img alt="商品图片" style={{ width: 100, height: 50 }} src={text} />,
    },
image

这个图片不能在当前页放大,或者直接在浏览器访问。
如果需要点击后在当前页面放大,这样的效果


放大

可以这么干,先撸一个imageView组件放在src/pages/Common下

import React, { PureComponent } from 'react';
import { Spin, Modal } from 'antd';

const defaultStyle = {
  borderRadius: 5,
  borderWidth: 1,
  borderStyle: 'solid',
  borderColor: '#d9d9d9',
  width: 70,
  height: 70,
  padding: 5,
  cursor: 'pointer',
  display: 'inline-flex',
  justifyContent: 'center',
  alignItems: 'center',
};

class ImageView extends PureComponent {
  state = {
    loading: true,
    visible: false,
    imgWidth: 0,
    imgHeight: 0,
  };

  componentDidMount() {
    this.init();
  }

  componentWillReceiveProps(nextProps) {
    const { url } = this.props;
    if (url !== nextProps.url) {
      this.init();
    }
  }

  init = () => {
    const { url } = this.props;
    if (url) {
      this.setState({ loading: true });
      const image = new Image();
      image.src = url;
      if (image.complete) {
        const size = this.getImageSize(image.width, image.height);
        this.setState({ loading: false, imgWidth: size.width, imgHeight: size.height });
      } else {
        image.onload = () => {
          const size = this.getImageSize(image.width, image.height);
          this.setState({ loading: false, imgWidth: size.width, imgHeight: size.height });
        };
      }
    }
  };

  getImageSize = (originImgWidth, originImgHeight) => {
    const { width, height } = this.props;
    const divWidth = (width || defaultStyle.width) - 2 * defaultStyle.padding;
    const divHeight = (height || defaultStyle.height) - 2 * defaultStyle.padding;
    const ratio = this.getRatio(originImgWidth, originImgHeight);
    const imgWidth = originImgWidth > originImgHeight ? divWidth : divWidth * ratio;
    const imgHeight = originImgHeight > originImgWidth ? divHeight : divHeight * ratio;
    return { width: imgWidth, height: imgHeight };
  };

  getRatio = (width, height) => (width < height ? width / height : height / width);

  render() {
    const { url, style } = this.props;
    const { loading, visible, imgWidth, imgHeight } = this.state;
    return (
      <span>
        {url ? (
          <span style={{ ...defaultStyle, ...style }}>
            {loading ? (
              <Spin />
            ) : (
              <img
                style={{ width: imgWidth, height: imgHeight }}
                alt="点击预览图片"
                src={url}
                onClick={() => {
                  this.setState({ visible: true });
                }}
              />
            )}
            <Modal
              style={{ top: 20 }}
              visible={visible}
              footer={null}
              onCancel={() => {
                this.setState({ visible: false });
              }}
            >
              <img alt="" style={{ width: '100%' }} src={url} />
            </Modal>
          </span>
        ) : (
          '无'
        )}
      </span>
    );
  }
}

export default ImageView;

然后table上这么用

    {
      title: '图片',
      dataIndex: 'itemImage',
      key: 'itemImage',
      render: (text, record) => <ImageView alt={record.title} url={text} />,
    },

3、长文本使用省略号

Ellipsis
    {
      title: '接收详情',
      dataIndex: 'receiveDesc',
      render: value => (
        <Ellipsis length={5} tooltip>
          {value}
        </Ellipsis>
      ),
    },

用到的Ellipsis是官网在components提供的通用组件。

4、可折叠table

image.png
  handleTableExpand = record => {
    const toTags = items => items.map((value, index) => <Tag key={index}>{value}</Tag>);
    return (
      <div>
        <DescriptionList size="small" col={1}>
          <Description term="资源IDS">{toTags(getResources(record.resourceIds))}</Description>
        </DescriptionList>
        <DescriptionList style={{ marginTop: 15 }} size="small">
          <Description term="短信验证码长度">{record.smsCodeLength}</Description>
          <Description term="短信验证码有效期">
            {record.smsCodeLength ? `${record.smsCodeExpire}分钟` : ''}
          </Description>
          <Description term="短信验证码签名">{record.smsCodeSign}</Description>
        </DescriptionList>
      </div>
    );
  };

然后在table上指定expandedRowRender={this.handleTableExpand}即可。

5、table显示总条数

total
  state: {
    query: { ...defaultQuery },
    list: {
      data: [],
      pagination: {},
    },
    exporting: false,
  },

  effects: {
    *fetch({ payload }, { call, put, select }) {
      yield put({ type: 'query', payload });
      const query = yield select(state => state.smsLog.query);
      const { data } = yield call(page, query);
      yield put({
        type: 'list',
        payload: {
          data: data.content,
          pagination: {
            current: data.number + 1,
            pageSize: data.size,
            total: Number(data.totalElements),
          },
        },
      });
    },
}

渲染时指定pagination的包括了total字段,所以就会显示出总条数。

<PageTable
            columns={this.columns}
              loading={loading}
              dataSource={list.data}
              pagination={list.pagination}
              onChange={this.handleTableChange}
            />

list就是从接口获取的数据,

6、表头支持筛选

筛选
{
       title: '人员状态',
       dataIndex: 'jobStatus',
       render:(text)=>{
           const filters = options.jobStatus.filter(s => s.value === text);
           return filters.length ? filters[0].text : '';
        },
       filters: options.jobStatus,
}

页面加载时加载个数据字典的值

    componentDidMount() {
        this.props.dispatch({type: 'rwUserOption/init'}).then(() => {
            this.props.dispatch({type: 'rwUserList/reload'});
        });
    }

请求字典数据:

import dict from '../../services/api-dict'

const optionKeys = [
    "RWGH-USER-XIAOWEI",
    "RWGH-USER-STATUS",
    'RWGH-TRAIN-ATTENDANCE'
];

export default {
    namespace: 'rwUserOption',
    state: {
        sex:[
            {text: '男', value: '0'},
            {text: '女', value: '1'}
        ],
        //小微
        xiaowei: [],
        //工作状态
        jobStatus: [],
        attendances: []
    },
    effects: {
        * init({payload}, {put, call}) {
            const [xiaowei, jobStatus, attendances] = yield call(dict.many, optionKeys);
            const mapper = (items) => {
                return items.map(item => {
                    const {dictValueName, dictValueCode} = item;
                    return {text: dictValueName, value: dictValueCode};
                })
            };
            yield put({type: 'changeXiaoWei', payload: mapper(xiaowei)});
            yield put({type: 'changeJobStatus', payload: mapper(jobStatus)});
            yield put({type: 'changeAttendances', payload: mapper(attendances)});
        }
    },
    reducers: {
        changeXiaoWei(state, {payload: xiaowei}) {
            return {...state, xiaowei}
        },
        changeJobStatus(state, {payload: jobStatus}) {
            return {...state, jobStatus}
        },
        changeAttendances(state, {payload: attendances}){
            return {...state, attendances}
        }
    }
}

dict.many是这样定义的:

import req from './api-base';

const dict = {
    one: (indexCode, cache = true) => {
        return new Promise(resolve => {
            const dict = sessionStorage.getItem(indexCode);
            if (cache && dict) {
                resolve(dict);
            } else {
                req.get("/questionnaire/admin/sys/dict/values", {indexCode}).then(data => {
                    sessionStorage.setItem(dict, data.data);
                    resolve(data.data)
                })
            }
        });
    },
    many: (indexCodes, cache = true) => {
        return Promise.all(indexCodes.map(code => dict.one(code, cache)));
    }
}

export default dict;

其中人员状态的数据结构如下:

{
    "code": 0,
    "message": "操作成功",
    "data": [
        {
            "dictValueId": 162,
            "dictIndexId": 148,
            "dictValueCode": "0",
            "dictValueName": "在职",
            "deleteFlag": "0",
            "dictValueSort": 0
        },
        {
            "dictValueId": 163,
            "dictIndexId": 148,
            "dictValueCode": "1",
            "dictValueName": "产假",
            "deleteFlag": "0",
            "dictValueSort": 1
        },
        {
            "dictValueId": 164,
            "dictIndexId": 148,
            "dictValueCode": "2",
            "dictValueName": "离职",
            "deleteFlag": "0",
            "dictValueSort": 2
        },
        {
            "dictValueId": 165,
            "dictIndexId": 148,
            "dictValueCode": "3",
            "dictValueName": "退休",
            "deleteFlag": "0",
            "dictValueSort": 3
        },
        {
            "dictValueId": 167,
            "dictIndexId": 148,
            "dictValueCode": "4",
            "dictValueName": "转岗",
            "deleteFlag": "0",
            "dictValueSort": 4
        },
        {
            "dictValueId": 168,
            "dictIndexId": 148,
            "dictValueCode": "5",
            "dictValueName": "病假",
            "deleteFlag": "0",
            "dictValueSort": 5
        }
    ]
}

这个筛选是多选的,选中后点击确定会触发查询,参数会xiaoweis=XSJDXW%2CXHYXW像这样拼接到url里。

7、结果转enum显示文本,如订单状态等。

const sendResultDom = {
  success: <Badge status="success" text="成功" />,
  error: <Badge status="error" text="失败" />,
};
    {
      title: '发送结果',
      dataIndex: 'sendResult',
      render: test => (test === '0' ? sendResultDom.success : sendResultDom.error),
    },

这种适合于这个对应值比较稳定变动较小的情况,如果是经常修改或者适配新增,又不改代码的话,就需要以数据字典的形式提供给页面字典数据,然后用组件去适配显示内容。

比如数据字典的sysDict/value/code/list?indexCode=sms_receive_result数据结构如下:

{
    "code": 0,
    "message": "操作成功",
    "data": [
        {
            "id": "88685502718279680",
            "isDelete": false,
            "createTime": 1553756821000,
            "updateTime": 1553756821000,
            "parentId": "88685399781670912",
            "name": "成功",
            "code": "0",
            "sort": 0,
            "type": 1,
            "remark": ""
        },
        {
            "id": "88685542446727168",
            "isDelete": false,
            "createTime": 1553756830000,
            "updateTime": 1553756830000,
            "parentId": "88685399781670912",
            "name": "失败",
            "code": "1",
            "sort": 1,
            "type": 1,
            "remark": ""
        },
        {
            "id": "88685595827634176",
            "isDelete": false,
            "createTime": 1553756843000,
            "updateTime": 1553756843000,
            "parentId": "88685399781670912",
            "name": "等待",
            "code": "-1",
            "sort": 2,
            "type": 1,
            "remark": ""
        }
    ]
}

然后写一个DictValue的组件:

/* eslint-disable */
import React, { PureComponent } from 'react';
import { Spin, Select } from 'antd';
import _ from 'lodash';
import memoizeOne from 'memoize-one';
import { valueListByIndexCode } from '@/services/dict';

const dictCache = {};

const filterValue = (dicts, value) => _.find(dicts, d => d.code === value);
const memoizeGetValue = memoizeOne(filterValue);

async function getIndexValues(index) {
  const values = dictCache[index];
  if (values) return values;
  const { data } = await valueListByIndexCode({ indexCode: index });
  const newValues = data.map(d => ({ name: d.name, code: d.code, remark: d.remark }));
  dictCache[index] = newValues;
  return newValues;
}

export async function getValue(index, value) {
  const indexValues = await getIndexValues(index);
  return memoizeGetValue(indexValues, value);
}

async function getValueName(index, value) {
  const indexValue = await getValue(index, value);
  return indexValue ? indexValue.name : value;
}

export class DictValue extends PureComponent {
  state = {
    loading: false,
    text: '',
  };

  componentDidMount() {
    const { index, value } = this.props;
    this.loadDate(index, value);
  }

  componentWillReceiveProps(nextProps) {
    const { index, value } = nextProps;
    const { props } = this;
    if (props.index !== index || props.value !== value) {
      this.loadDate(index, value);
    }
  }

  loadDate = (index, value) => {
    if (!value) {
      this.setState({ text: '', loading: false });
      return;
    }
    this.setState({ loading: true });
    getValueName(index, value).then(text => {
      this.setState({ text, loading: false });
    });
  };

  render() {
    const { loading, text } = this.state;
    return <span>{loading ? <Spin size="small" /> : `${text}`}</span>;
  }
}

const { Option } = Select;

export class DictSelect extends PureComponent {
  state = {
    data: [],
  };

  componentDidMount() {
    const { index } = this.props;
    getIndexValues(index).then(data => {
      this.setState({ data });
    });
  }

  render() {
    const { props } = this;
    const { data } = this.state;
    return (
      <Select placeholder="请选择" {...props}>
        {data.map(item => (
          <Option key={item.code} value={item.code}>
            {item.name}
          </Option>
        ))}
      </Select>
    );
  }
}

其中valueListByIndexCode就是获取到上面结构数据的api,不用特殊说明了。
这个类包含了两个方法,一个是DictValue,用来从key获取value,一个是DictSelect提供一下该字典值得下拉选项。
DictValue的用法:

{
      title: '接收结果',
      dataIndex: 'receiveResult',
      render: value => <DictValue index="sms_receive_result" value={value} />,
},

DictSelect的用法:

<FormItem label="接收结果">
    <DictSelect
       allowClear
       index="sms_receive_result"
       value={query.receiveResult}
       onChange={receiveResult => this.handleSearch({ receiveResult })}
    />
</FormItem>

8、等待。。。

官方API

相关文章

网友评论

      本文标题:Ant Design Pro 学习之table使用

      本文链接:https://www.haomeiwen.com/subject/tvmwgqtx.html