Ant Design Pro学习之组件化

同事写了一个我目前看着比较正规化的组件式页面,在此作为学习标准贴一下,先看个效果图:


列表
编辑1
编辑2

这是一个oauth的client管理的页面,主要代码如下:
api列表数据结构

{
    "code": 0,
    "message": "操作成功",
    "data": {
        "content": [
            {
                "clientId": "usercenter-manage",
                "clientName": "测试app",
                "resourceIds": "usercenter/manage,smscenter/api",
                "clientSecret": "",
                "scope": "read,write,trust",
                "authorizedGrantTypes": "password,refresh_token",
                "webServerRedirectUri": null,
                "authorities": null,
                "accessTokenValidity": 7200,
                "refreshTokenValidity": null,
                "additionalInformation": null,
                "autoapprove": null,
                "smsCodeLength": 4,
                "smsCodeExpire": 10,
                "smsCodeSign": "【xxxxxx】",
                "platformCode": null,
                "updateTime": "2019-03-25T14:27:26.000+0000",
                "createTime": null
            }
        ],
        "pageable": {
            "sort": {
                "sorted": true,
                "unsorted": false,
                "empty": false
            },
            "offset": 0,
            "pageSize": 10,
            "pageNumber": 0,
            "paged": true,
            "unpaged": false
        },
        "totalPages": 1,
        "totalElements": 9,
        "last": true,
        "size": 10,
        "number": 0,
        "first": true,
        "numberOfElements": 9,
        "sort": {
            "sorted": true,
            "unsorted": false,
            "empty": false
        },
        "empty": false
    }
}

组件化嘛,文件自然比较多,打个标识

1、ClientList:页面渲染js

import React, { PureComponent } from 'react';
import { connect } from 'dva';
import { Popconfirm, Card, Table, Button, Divider, Tag, message } from 'antd';
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
import DescriptionList from '@/components/DescriptionList';
import ClientForm from './ClientForm';
import { humanizeTime, getOAuthTypeNames } from './ClientUtil';
import styles from '../Common/TableList.less';

const { Description } = DescriptionList;

@connect(({ client, loading }) => ({
  client,
  loading: loading.effects['client/fetch'],
  submitting: loading.effects['client/update'],
}))
class ClientList extends PureComponent {
  columns = [
    {
      title: '应用ID',
      dataIndex: 'clientId',
    },
    {
      title: '应用名称',
      dataIndex: 'clientName',
    },
    {
      title: (
        
          Token
          
有效期
), dataIndex: 'accessTokenValidity', render: value => humanizeTime(value), }, { title: ( RefreshToken
有效期
), dataIndex: 'refreshTokenValidity', render: value => humanizeTime(value), }, { title: '操作', dataIndex: 'action', render: (text, record) => ( { this.handleOpenForm(record); }} > 编辑 { this.handleRemove(record); }} okText="确认" cancelText="取消" > 删除 ), }, ]; componentDidMount() { const { dispatch } = this.props; dispatch({ type: 'client/fetch' }); } handleTableChange = pagination => { const { current, pageSize } = pagination; const { dispatch } = this.props; dispatch({ type: 'client/fetch', payload: { page: current - 1, size: pageSize } }); }; handleTableExpand = record => { const toTags = items => items.map((value, index) => {value}); return (
{toTags(getOAuthTypeNames(record.authorizedGrantTypes))} {record.platformCode} {record.resourceIds} {record.smsCodeLength} {record.smsCodeLength ? `${record.smsCodeLength}分钟` : ''} {record.smsCodeSign}
); }; handleOpenForm = formData => { const { dispatch } = this.props; dispatch({ type: 'client/openForm', payload: formData }); }; handleCloseForm = () => { const { dispatch } = this.props; dispatch({ type: 'client/closeForm' }); }; handleAdd = values => { const { dispatch } = this.props; dispatch({ type: 'client/update', payload: values }).then(() => { message.success('操作成功'); }); }; handleRemove = record => { const { dispatch } = this.props; dispatch({ type: 'client/remove', payload: record.clientId }).then(() => { message.success('删除成功'); }); }; render() { const { client: { list, form }, loading, submitting, } = this.props; const paginationProps = { showSizeChanger: true, showQuickJumper: true, ...list.pagination, }; return (
); } } export default ClientList;

2、ClientForm:添加编辑单条数据的Form

import React, { PureComponent } from 'react';
import { Modal, Form, Input, Tabs, InputNumber } from 'antd';
import SecretInput from './SecretInput';
import PeriodInput from './PeriodInput';
import GrantTypeInput from './GrantTypeInput';
import SmsSignInput from './SmsSignInput';

const { Item: FormItem } = Form;
const { TabPane } = Tabs;

@Form.create()
class ClientForm extends PureComponent {
  state = {
    tabKey: '1',
  };

  reset = () => {
    const { form } = this.props;
    form.resetFields();
    this.setState({ tabKey: '1' });
  };

  render() {
    const { data, visible, submitting, onSave, onClose, form } = this.props;
    const { tabKey } = this.state;
    const formItemLayout = {
      labelCol: { span: 5 },
      wrapperCol: { span: 15 },
    };
    const title = data.clientId ? '更新应用' : '添加应用';
    return (
       {
          this.reset();
          onClose();
        }}
        onOk={() => {
          form.validateFields((err, values) => {
            if (!err) onSave(values);
            else this.setState({ tabKey: '1' });
          });
        }}
      >
        
this.setState({ tabKey: activeKey })} > {form.getFieldDecorator('clientId', { rules: [ { type: 'string', required: true, message: '应用ID不能为空!', }, ], initialValue: data.clientId, })()} {form.getFieldDecorator('clientName', { rules: [ { type: 'string', required: true, message: '应用名称不能为空!', }, ], initialValue: data.clientName, })()} {form.getFieldDecorator('resourceIds', { rules: [ { type: 'string', required: true, message: '资源IDs不能为空!', }, ], initialValue: data.resourceIds, })()} {form.getFieldDecorator('authorizedGrantTypes', { rules: [ { type: 'string', required: true, message: '请选择授权类型!', }, ], initialValue: data.authorizedGrantTypes, })()} {form.getFieldDecorator('accessTokenValidity', { initialValue: _.defaultTo(data.accessTokenValidity, ''), })()} {form.getFieldDecorator('refreshTokenValidity', { initialValue: _.defaultTo(data.refreshTokenValidity, ''), })()} {form.getFieldDecorator('clientSecret', { initialValue: _.defaultTo(data.clientSecret, ''), })()} {form.getFieldDecorator('smsCodeLength', { initialValue: data.smsCodeLength, })()} {form.getFieldDecorator('smsCodeExpire', { initialValue: data.smsCodeExpire, })()} {form.getFieldDecorator('smsCodeSign', { initialValue: data.smsCodeSign, })()}
); } } export default ClientForm;

3、ClientUtil.js

import _ from 'lodash';
import moment from 'moment';
export const authTypes = [
  { name: '授权码模式', value: 'authorization_code' },
  { name: '简化模式', value: 'implicit' },
  { name: '密码模式', value: 'password' },
  { name: '客户端模式', value: 'client_credentials' },
  { name: '刷新模式', value: 'refresh_token' },
];
export function getOAuthTypeNames(str) {
  if (!str) return [];
  const values = str.split(',');
  return values.map(value => _.find(authTypes, t => t.value === value).name);
}
export function getResources(str) {
  if (!str) return [];
  return str.split(',');
}
export function humanizeTime(value) {
  let timeText = '';
  if (value) {
    timeText = moment.duration(value, 'seconds').humanize();
  } else {
    timeText = '未设置';
  }
  return timeText;
}

4、GrantTypeInput组件GrantTypeInput.js

GrantTypeInput
import React, { PureComponent } from 'react';
import { Select } from 'antd';
import { authTypes } from './ClientUtil';

const { Option } = Select;

class GrantTypeInput extends PureComponent {
  state = {
    value: [],
  };

  componentWillMount() {
    const { props } = this;
    if (props.value) {
      const value = props.value ? props.value.split(',') : [];
      this.setState({ value });
    }
  }

  componentWillReceiveProps(nextProps) {
    const { props } = this;
    if (props.value !== nextProps.value && !nextProps.value) {
      this.setState({ value: [] });
    } else {
      const value = nextProps.value ? nextProps.value.split(',') : [];
      this.setState({ value });
    }
  }

  handleSelectChange = value => {
    const { onChange } = this.props;
    this.setState({ value });
    if (onChange) onChange(value.join(','));
  };

  render() {
    const { value } = this.state;
    return (
      
    );
  }
}

export default GrantTypeInput;

5、token有效期输入组件PeriodInput.js

PeriodInput.js
import React, { PureComponent } from 'react';
import moment from 'moment';

import { Input, Select } from 'antd';

const { Option } = Select;

const getTime = (time, fromUnit, toUnit) => moment.duration(Number(time), fromUnit).as(toUnit);

export const timeUnits = [
  { name: '秒', value: 'seconds' },
  { name: '分钟', value: 'minutes' },
  { name: '小时', value: 'hours' },
  { name: '天', value: 'days' },
];

class PeriodInput extends PureComponent {
  state = {
    value: '',
    unit: 'seconds',
  };

  componentWillMount() {
    const { props } = this;
    if (props.value) {
      this.setState({
        unit: 'seconds',
        value: props.value,
      });
    }
  }

  componentWillReceiveProps(nextProps) {
    const { props } = this;
    if (props.value !== nextProps.value && !nextProps.value) {
      this.setState({
        unit: 'seconds',
        value: '',
      });
    } else {
      this.setState({
        unit: 'seconds',
        value: nextProps.value,
      });
    }
  }

  handleSelectChange = unitValue => {
    const { unit, value } = this.state;
    const newValue = value ? getTime(value, unit, unitValue) : '';
    this.setState({
      unit: unitValue,
      value: newValue,
    });
  };

  onChangeValue = e => {
    const { value } = e.target;
    const { unit } = this.state;
    const { onChange } = this.props;
    const seconds = getTime(value, unit, 'seconds');
    this.setState({ value });
    if (onChange) onChange(seconds);
  };

  render() {
    const { unit, value } = this.state;
    return (
      
            {timeUnits.map(t => (
              
            ))}
          
        }
      />
    );
  }
}

export default PeriodInput;

6、秘钥生成组件SecretInput.js

SecretInput
import React, { PureComponent } from 'react';
import { Row, Col, Slider, Input } from 'antd';
import random from '@/utils/random';

const minValue = 10;
const maxValue = 30;
const defaultState = {
  visible: false,
  value: '',
  length: 10,
};

class SecretInput extends PureComponent {
  state = { ...defaultState };

  componentWillMount() {
    const { props } = this;
    if (props.value) {
      this.setState({ value: props.value });
    }
  }

  componentWillReceiveProps(nextProps) {
    const { props } = this;
    if (props.value !== nextProps.value && !nextProps.value) {
      this.setState({ ...defaultState });
    } else {
      this.setState({ value: nextProps.value });
    }
  }

  handleCreatePwd = () => {
    const { length } = this.state;
    this.setState({ visible: true });
    this.handleChangeLength(length);
  };

  handleChangeLength = length => {
    const value = random.generate(length);
    this.setState({ length });
    this.handleChangeValue(value);
  };

  handleChangeValue = value => {
    const { onChange } = this.props;
    this.setState({ value });
    if (onChange) onChange(value);
  };

  render() {
    const { visible, value, length } = this.state;
    return (
      
随机生成 {visible ? ( ) : null} ); } } export default SecretInput;

7、短信签名:输入内容与数据库保存不一致,前端正则加减括号

import React, { PureComponent } from 'react';
import { Input } from 'antd';

const removeBrackets = value => (value ? value.replace(/[【】]/g, '') : '');
const addBrackets = value => (value ? `【${value}】` : '');

class SmsSignInput extends PureComponent {
  state = {
    value: '',
  };

  componentWillMount() {
    const { props } = this;
    if (props.value) this.setStateValue(props.value);
  }

  componentWillReceiveProps(nextProps) {
    const { props } = this;
    if (props.value !== nextProps.value && !nextProps.value) {
      this.setStateValue('');
    } else {
      this.setStateValue(nextProps.value);
    }
  }

  setStateValue = value => {
    this.setState({ value: removeBrackets(value) });
  };

  handleChangeValue = e => {
    const { value } = e.target;
    const { onChange } = this.props;
    this.setState({ value });
    if (onChange) onChange(addBrackets(value));
  };

  render() {
    const { value } = this.state;
    const { props } = this;
    return ;
  }
}

export default SmsSignInput;

你可能感兴趣的:(Ant Design Pro学习之组件化)