美文网首页
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