Przeglądaj źródła

Merge branch 'v2' of https://github.com/ant-design/ant-design-pro into v2

ddcat1115 7 lat temu
rodzic
commit
509e432cfe

+ 0 - 1
.roadhogrc.mock.js

@@ -2,7 +2,6 @@ import mockjs from 'mockjs';
 import { getRule, postRule } from './mock/rule';
 import { getActivities, getNotice, getFakeList, postFakeList } from './mock/api';
 import { getFakeChartData } from './mock/chart';
-import { imgMap } from './mock/utils';
 import { getProfileBasicData } from './mock/profile';
 import { getProfileAdvancedData } from './mock/profile';
 import { getNotices } from './mock/notices';

+ 2 - 2
mock/api.js

@@ -1,4 +1,4 @@
-import { getUrlParams } from './utils';
+import { parse } from 'url';
 
 const titles = [
   'Alipay',
@@ -115,7 +115,7 @@ export function getFakeList(req, res, u) {
     url = req.url; // eslint-disable-line
   }
 
-  const params = getUrlParams(url);
+  const params = parse(url, true).query;
 
   const count = (params.count * 1) || 20;
 

+ 2 - 2
mock/rule.js

@@ -1,4 +1,4 @@
-import { getUrlParams } from './utils';
+import { parse } from 'url';
 
 // mock tableListDataSource
 let tableListDataSource = [];
@@ -26,7 +26,7 @@ export function getRule(req, res, u) {
     url = req.url; // eslint-disable-line
   }
 
-  const params = getUrlParams(url);
+  const params = parse(url, true).query;
 
   let dataSource = [...tableListDataSource];
 

+ 0 - 45
mock/utils.js

@@ -1,45 +0,0 @@
-export const imgMap = {
-  user: 'https://gw.alipayobjects.com/zos/rmsportal/UjusLxePxWGkttaqqmUI.png',
-  a: 'https://gw.alipayobjects.com/zos/rmsportal/ZrkcSjizAKNWwJTwcadT.png',
-  b: 'https://gw.alipayobjects.com/zos/rmsportal/KYlwHMeomKQbhJDRUVvt.png',
-  c: 'https://gw.alipayobjects.com/zos/rmsportal/gabvleTstEvzkbQRfjxu.png',
-  d: 'https://gw.alipayobjects.com/zos/rmsportal/jvpNzacxUYLlNsHTtrAD.png',
-};
-
-// refers: https://www.sitepoint.com/get-url-parameters-with-javascript/
-export function getUrlParams(url) {
-  const d = decodeURIComponent;
-  let queryString = url ? url.split('?')[1] : window.location.search.slice(1);
-  const obj = {};
-  if (queryString) {
-    queryString = queryString.split('#')[0]; // eslint-disable-line
-    const arr = queryString.split('&');
-    for (let i = 0; i < arr.length; i += 1) {
-      const a = arr[i].split('=');
-      let paramNum;
-      const paramName = a[0].replace(/\[\d*\]/, (v) => {
-        paramNum = v.slice(1, -1);
-        return '';
-      });
-      const paramValue = typeof (a[1]) === 'undefined' ? true : a[1];
-      if (obj[paramName]) {
-        if (typeof obj[paramName] === 'string') {
-          obj[paramName] = d([obj[paramName]]);
-        }
-        if (typeof paramNum === 'undefined') {
-          obj[paramName].push(d(paramValue));
-        } else {
-          obj[paramName][paramNum] = d(paramValue);
-        }
-      } else {
-        obj[paramName] = d(paramValue);
-      }
-    }
-  }
-  return obj;
-}
-
-export default {
-  getUrlParams,
-  imgMap,
-};

+ 0 - 5
src/common/menu.js

@@ -113,11 +113,6 @@ const menuData = [{
     name: '注册结果',
     path: 'register-result',
   }],
-}, {
-  name: '使用文档',
-  icon: 'book',
-  path: 'http://pro.ant.design/docs/getting-started',
-  target: '_blank',
 }];
 
 function formatter(data, parentPath = '', parentAuthority) {

+ 73 - 66
src/components/Charts/Radar/index.js

@@ -60,7 +60,9 @@ export default class Radar extends Component {
     const { legendData } = this.state;
     legendData[i] = newItem;
 
-    const filteredLegendData = legendData.filter(l => l.checked).map(l => l.name);
+    const filteredLegendData = legendData
+      .filter(l => l.checked)
+      .map(l => l.name);
 
     if (this.chart) {
       this.chart.filter('name', val => filteredLegendData.indexOf(val) > -1);
@@ -109,71 +111,76 @@ export default class Radar extends Component {
 
     return (
       <div className={styles.radar} style={{ height }}>
-        <div>
-          {title && <h4>{title}</h4>}
-          <Chart
-            scale={scale}
-            height={chartHeight}
-            forceFit={forceFit}
-            data={data}
-            padding={padding}
-            animate={animate}
-            onGetG2Instance={this.getG2Instance}
-          >
-            <Tooltip />
-            <Coord type="polar" />
-            <Axis
-              name="label"
-              line={null}
-              tickLine={null}
-              grid={{
-                lineStyle: {
-                  lineDash: null,
-                },
-                hideFirstLine: false,
-              }}
-            />
-            <Axis
-              name="value"
-              grid={{
-                type: 'polygon',
-                lineStyle: {
-                  lineDash: null,
-                },
-              }}
-            />
-            <Geom type="line" position="label*value" color={['name', colors]} size={1} />
-            <Geom
-              type="point"
-              position="label*value"
-              color={['name', colors]}
-              shape="circle"
-              size={3}
-            />
-          </Chart>
-          {hasLegend && (
-            <Row className={styles.legend}>
-              {legendData.map((item, i) => (
-                <Col
-                  span={24 / legendData.length}
-                  key={item.name}
-                  onClick={() => this.handleLegendClick(item, i)}
-                >
-                  <div className={styles.legendItem}>
-                    <p>
-                      <span
-                        className={styles.dot}
-                        style={{ backgroundColor: !item.checked ? '#aaa' : item.color }}
-                      />
-                      <span>{item.name}</span>
-                    </p>
-                    <h6>{item.value}</h6>
-                  </div>
-                </Col>
-              ))}
-            </Row>
-          )}
-        </div>
+        {title && <h4>{title}</h4>}
+        <Chart
+          scale={scale}
+          height={chartHeight}
+          forceFit={forceFit}
+          data={data}
+          padding={padding}
+          animate={animate}
+          onGetG2Instance={this.getG2Instance}
+        >
+          <Tooltip />
+          <Coord type="polar" />
+          <Axis
+            name="label"
+            line={null}
+            tickLine={null}
+            grid={{
+              lineStyle: {
+                lineDash: null,
+              },
+              hideFirstLine: false,
+            }}
+          />
+          <Axis
+            name="value"
+            grid={{
+              type: 'polygon',
+              lineStyle: {
+                lineDash: null,
+              },
+            }}
+          />
+          <Geom
+            type="line"
+            position="label*value"
+            color={['name', colors]}
+            size={1}
+          />
+          <Geom
+            type="point"
+            position="label*value"
+            color={['name', colors]}
+            shape="circle"
+            size={3}
+          />
+        </Chart>
+        {hasLegend && (
+          <Row className={styles.legend}>
+            {legendData.map((item, i) => (
+              <Col
+                span={24 / legendData.length}
+                key={item.name}
+                onClick={() => this.handleLegendClick(item, i)}
+              >
+                <div className={styles.legendItem}>
+                  <p>
+                    <span
+                      className={styles.dot}
+                      style={{
+                        backgroundColor: !item.checked ? '#aaa' : item.color,
+                      }}
+                    />
+                    <span>{item.name}</span>
+                  </p>
+                  <h6>{item.value}</h6>
+                </div>
+              </Col>
+           ))}
+          </Row>
+        )}
       </div>
     );
   }

+ 3 - 5
src/components/Ellipsis/index.d.ts

@@ -1,12 +1,10 @@
-import * as React from "react";
+import * as React from 'react';
 export interface EllipsisProps {
   tooltip?: boolean;
   length?: number;
   lines?: number;
   style?: React.CSSProperties;
+  className?: string;
 }
 
-export default class Ellipsis extends React.Component<
-  EllipsisProps,
-  any
-> {}
+export default class Ellipsis extends React.Component<EllipsisProps, any> {}

+ 28 - 20
src/components/FooterToolbar/demo/basic.md

@@ -1,36 +1,44 @@
 ---
 order: 0
-title: 演示
+title:
+  - zh-CN: 演示
+  - en-US: demo
 iframe: 400
 ---
 
+## zh-CN
+
 浮动固定页脚。
 
+## en-US
+
+Fixed to the footer.
+
 ````jsx
 import FooterToolbar from 'ant-design-pro/lib/FooterToolbar';
 import { Button } from 'antd';
 
 ReactDOM.render(
   <div style={{ background: '#f7f7f7', padding: 24 }}>
-    <p>页面内容 页面内容 页面内容 页面内容</p>
-    <p>页面内容 页面内容 页面内容 页面内容</p>
-    <p>页面内容 页面内容 页面内容 页面内容</p>
-    <p>页面内容 页面内容 页面内容 页面内容</p>
-    <p>页面内容 页面内容 页面内容 页面内容</p>
-    <p>页面内容 页面内容 页面内容 页面内容</p>
-    <p>页面内容 页面内容 页面内容 页面内容</p>
-    <p>页面内容 页面内容 页面内容 页面内容</p>
-    <p>页面内容 页面内容 页面内容 页面内容</p>
-    <p>页面内容 页面内容 页面内容 页面内容</p>
-    <p>页面内容 页面内容 页面内容 页面内容</p>
-    <p>页面内容 页面内容 页面内容 页面内容</p>
-    <p>页面内容 页面内容 页面内容 页面内容</p>
-    <p>页面内容 页面内容 页面内容 页面内容</p>
-    <p>页面内容 页面内容 页面内容 页面内容</p>
-    <FooterToolbar extra="提示信息">
-      <Button>取消</Button>
-      <Button type="primary">提交</Button>
+    <p>Content Content Content Content</p>
+    <p>Content Content Content Content</p>
+    <p>Content Content Content Content</p>
+    <p>Content Content Content Content</p>
+    <p>Content Content Content Content</p>
+    <p>Content Content Content Content</p>
+    <p>Content Content Content Content</p>
+    <p>Content Content Content Content</p>
+    <p>Content Content Content Content</p>
+    <p>Content Content Content Content</p>
+    <p>Content Content Content Content</p>
+    <p>Content Content Content Content</p>
+    <p>Content Content Content Content</p>
+    <p>Content Content Content Content</p>
+    <p>Content Content Content Content</p>
+    <FooterToolbar extra="extra information">
+      <Button>Cancel</Button>
+      <Button type="primary">Submit</Button>
     </FooterToolbar>
   </div>
 , mountNode);
-````
+````

+ 18 - 0
src/components/FooterToolbar/index.en-US.md

@@ -0,0 +1,18 @@
+---
+title: FooterToolbar
+cols: 1
+order: 6
+---
+
+A toolbar fixed at the bottom.
+
+## Usage
+
+It is fixed at the bottom of the content area and does not move along with the scroll bar, which is usually used for data collection and submission for long pages.
+
+## API
+
+Property | Description | Type | Default
+---------|-------------|------|--------
+children | toolbar content, align to the right | ReactNode | -
+extra | extra information, align to the left | ReactNode | -

+ 1 - 3
src/components/FooterToolbar/index.md

@@ -1,7 +1,5 @@
 ---
-title:
-  en-US: FooterToolbar
-  zh-CN: FooterToolbar
+title: FooterToolbar
 subtitle: 底部工具栏
 cols: 1
 order: 6

+ 11 - 1
src/components/GlobalHeader/index.js

@@ -1,5 +1,5 @@
 import React, { PureComponent } from 'react';
-import { Menu, Icon, Spin, Tag, Dropdown, Avatar, Divider } from 'antd';
+import { Menu, Icon, Spin, Tag, Dropdown, Avatar, Divider, Tooltip } from 'antd';
 import moment from 'moment';
 import groupBy from 'lodash/groupBy';
 import Debounce from 'lodash-decorators/debounce';
@@ -94,6 +94,16 @@ export default class GlobalHeader extends PureComponent {
               console.log('enter', value); // eslint-disable-line
             }}
           />
+          <Tooltip title="使用文档">
+            <a
+              target="_blank"
+              href="http://pro.ant.design/docs/getting-started"
+              rel="noopener noreferrer"
+              className={styles.action}
+            >
+              <Icon type="question-circle-o" />
+            </a >
+          </Tooltip>
           <NoticeIcon
             className={styles.action}
             count={currentUser.notifyCount}

+ 1 - 0
src/components/GlobalHeader/index.less

@@ -61,6 +61,7 @@ i.trigger {
     > i {
       font-size: 16px;
       vertical-align: middle;
+      color: @text-color;
     }
     &:hover,
     &:global(.ant-popover-open) {

+ 12 - 6
src/components/PageHeader/index.js

@@ -7,8 +7,7 @@ import styles from './index.less';
 
 
 const { TabPane } = Tabs;
-
-function getBreadcrumb(breadcrumbNameMap, url) {
+export function getBreadcrumb(breadcrumbNameMap, url) {
   let breadcrumb = breadcrumbNameMap[url];
   if (!breadcrumb) {
     Object.keys(breadcrumbNameMap).forEach((item) => {
@@ -20,6 +19,14 @@ function getBreadcrumb(breadcrumbNameMap, url) {
   return breadcrumb || {};
 }
 
+// /userinfo/2144/id => ['/userinfo','/useinfo/2144,'/userindo/2144/id']
+export function urlToList(url) {
+  const urllist = url.split('/').filter(i => i);
+  return urllist.map((urlItem, index) => {
+    return `/${urllist.slice(0, index + 1).join('/')}`;
+  });
+}
+
 export default class PageHeader extends PureComponent {
   static contextTypes = {
     routes: PropTypes.array,
@@ -62,11 +69,10 @@ export default class PageHeader extends PureComponent {
   }
   conversionFromLocation = (routerLocation, breadcrumbNameMap) => {
     const { breadcrumbSeparator, linkElement = 'a' } = this.props;
-    // Convert the path to an array
-    const pathSnippets = routerLocation.pathname.split('/').filter(i => i);
+    // Convert the url to an array
+    const pathSnippets = urlToList(routerLocation.pathname);
     // Loop data mosaic routing
-    const extraBreadcrumbItems = pathSnippets.map((_, index) => {
-      const url = `/${pathSnippets.slice(0, index + 1).join('/')}`;
+    const extraBreadcrumbItems = pathSnippets.map((url, index) => {
       const currentBreadcrumb = getBreadcrumb(breadcrumbNameMap, url);
       const isLinkable = (index !== pathSnippets.length - 1) && currentBreadcrumb.component;
       return currentBreadcrumb.name && !currentBreadcrumb.hideInBreadcrumb ? (

+ 71 - 0
src/components/PageHeader/index.test.js

@@ -0,0 +1,71 @@
+import { getBreadcrumb, urlToList } from './index';
+
+describe('test urlToList', () => {
+  it('A path', () => {
+    expect(urlToList('/userinfo')).toEqual(['/userinfo']);
+  });
+  it('Secondary path', () => {
+    expect(urlToList('/userinfo/2144')).toEqual([
+      '/userinfo',
+      '/userinfo/2144',
+    ]);
+  });
+  it('Three paths', () => {
+    expect(urlToList('/userinfo/2144/addr')).toEqual([
+      '/userinfo',
+      '/userinfo/2144',
+      '/userinfo/2144/addr',
+    ]);
+  });
+});
+
+const routerData = {
+  '/dashboard/analysis': {
+    name: '分析页',
+  },
+  '/userinfo': {
+    name: '用户列表',
+  },
+  '/userinfo/:id': {
+    name: '用户信息',
+  },
+  '/userinfo/:id/addr': {
+    name: '收货订单',
+  },
+};
+describe('test getBreadcrumb', () => {
+  it('Simple url', () => {
+    expect(getBreadcrumb(routerData, '/dashboard/analysis').name).toEqual(
+      '分析页'
+    );
+  });
+  it('Parameters url', () => {
+    expect(getBreadcrumb(routerData, '/userinfo/2144').name).toEqual(
+      '用户信息'
+    );
+  });
+  it('The middle parameter url', () => {
+    expect(getBreadcrumb(routerData, '/userinfo/2144/addr').name).toEqual(
+      '收货订单'
+    );
+  });
+  it('Loop through the parameters', () => {
+    const urlNameList = urlToList('/userinfo/2144/addr').map((url) => {
+      return getBreadcrumb(routerData, url).name;
+    });
+    expect(urlNameList).toEqual(['用户列表', '用户信息', '收货订单']);
+  });
+
+  it('a path', () => {
+    const urlNameList = urlToList('/userinfo').map((url) => {
+      return getBreadcrumb(routerData, url).name;
+    });
+    expect(urlNameList).toEqual(['用户列表']);
+  });
+  it('Secondary path', () => {
+    const urlNameList = urlToList('/userinfo/2144').map((url) => {
+      return getBreadcrumb(routerData, url).name;
+    });
+    expect(urlNameList).toEqual(['用户列表', '用户信息']);
+  });
+});

+ 2 - 2
src/components/SiderMenu/SiderMenu.js

@@ -87,12 +87,12 @@ export default class SiderMenu extends PureComponent {
   }
   /**
    * Get selected child nodes
-   * /user/chen => /user/:id
+   * /user/chen => ['user','/user/:id']
    */
   getSelectedMenuKeys = (path) => {
     const flatMenuKeys = this.getFlatMenuKeys(this.menus);
     return flatMenuKeys.filter((item) => {
-      return pathToRegexp(`/${item}`).test(path);
+      return pathToRegexp(`/${item}(.*)`).test(path);
     });
   }
   /**

+ 3 - 3
src/components/StandardTable/index.js

@@ -1,4 +1,4 @@
-import React, { PureComponent } from 'react';
+import React, { PureComponent, Fragment } from 'react';
 import { Table, Alert } from 'antd';
 import styles from './index.less';
 
@@ -84,7 +84,7 @@ class StandardTable extends PureComponent {
         <div className={styles.tableAlert}>
           <Alert
             message={(
-              <div>
+              <Fragment>
                 已选择 <a style={{ fontWeight: 600 }}>{selectedRowKeys.length}</a> 项&nbsp;&nbsp;
                 {
                   needTotalList.map(item => (
@@ -97,7 +97,7 @@ class StandardTable extends PureComponent {
                   )
                 }
                 <a onClick={this.cleanSelectedKeys} style={{ marginLeft: 24 }}>清空</a>
-              </div>
+              </Fragment>
             )}
             type="info"
             showIcon

+ 3 - 3
src/layouts/BasicLayout.js

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { Fragment } from 'react';
 import PropTypes from 'prop-types';
 import { Layout, Icon, message } from 'antd';
 import DocumentTitle from 'react-document-title';
@@ -230,9 +230,9 @@ class BasicLayout extends React.PureComponent {
                 blankTarget: true,
               }]}
               copyright={
-                <div>
+                <Fragment>
                   Copyright <Icon type="copyright" /> 2018 蚂蚁金服体验技术部出品
-                </div>
+                </Fragment>
               }
             />
           </Footer>

+ 2 - 2
src/layouts/UserLayout.js

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { Fragment } from 'react';
 import { Link, Redirect, Switch, Route } from 'dva/router';
 import DocumentTitle from 'react-document-title';
 import { Icon } from 'antd';
@@ -21,7 +21,7 @@ const links = [{
   href: '',
 }];
 
-const copyright = <div>Copyright <Icon type="copyright" /> 2018 蚂蚁金服体验技术部出品</div>;
+const copyright = <Fragment>Copyright <Icon type="copyright" /> 2018 蚂蚁金服体验技术部出品</Fragment>;
 
 class UserLayout extends React.PureComponent {
   getPageTitle() {

+ 3 - 3
src/routes/Dashboard/Analysis.js

@@ -1,4 +1,4 @@
-import React, { Component } from 'react';
+import React, { Component, Fragment } from 'react';
 import { connect } from 'dva';
 import {
   Row,
@@ -241,7 +241,7 @@ export default class Analysis extends Component {
     };
 
     return (
-      <div>
+      <Fragment>
         <Row gutter={24}>
           <Col {...topColResponsiveProps}>
             <ChartCard
@@ -482,7 +482,7 @@ export default class Analysis extends Component {
             ))}
           </Tabs>
         </Card>
-      </div>
+      </Fragment>
     );
   }
 }

+ 3 - 3
src/routes/Dashboard/Monitor.js

@@ -1,4 +1,4 @@
-import React, { PureComponent } from 'react';
+import React, { PureComponent, Fragment } from 'react';
 import { connect } from 'dva';
 import { Row, Col, Card, Tooltip } from 'antd';
 import numeral from 'numeral';
@@ -35,7 +35,7 @@ export default class Monitor extends PureComponent {
     const { tags } = monitor;
 
     return (
-      <div>
+      <Fragment>
         <Row gutter={24}>
           <Col xl={18} lg={24} md={24} sm={24} xs={24} style={{ marginBottom: 24 }}>
             <Card title="活动实时交易情况" bordered={false}>
@@ -164,7 +164,7 @@ export default class Monitor extends PureComponent {
             </Card>
           </Col>
         </Row>
-      </div>
+      </Fragment>
     );
   }
 }

+ 3 - 3
src/routes/Forms/StepForm/Step1.js

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { Fragment } from 'react';
 import { connect } from 'dva';
 import { Form, Input, Button, Select, Divider } from 'antd';
 import { routerRedux } from 'dva/router';
@@ -32,7 +32,7 @@ class Step1 extends React.PureComponent {
       });
     };
     return (
-      <div>
+      <Fragment>
         <Form layout="horizontal" className={styles.stepForm} hideRequiredMark>
           <Form.Item
             {...formItemLayout}
@@ -112,7 +112,7 @@ class Step1 extends React.PureComponent {
           <h4>转账到银行卡</h4>
           <p>如果需要,这里可以放一些关于产品的常见问题说明。如果需要,这里可以放一些关于产品的常见问题说明。如果需要,这里可以放一些关于产品的常见问题说明。</p>
         </div>
-      </div>
+      </Fragment>
     );
   }
 }

+ 3 - 3
src/routes/Forms/StepForm/Step3.js

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { Fragment } from 'react';
 import { connect } from 'dva';
 import { Button, Row, Col } from 'antd';
 import { routerRedux } from 'dva/router';
@@ -32,14 +32,14 @@ class Step3 extends React.PureComponent {
       </div>
     );
     const actions = (
-      <div>
+      <Fragment>
         <Button type="primary" onClick={onFinish}>
           再转一笔
         </Button>
         <Button>
           查看账单
         </Button>
-      </div>
+      </Fragment>
     );
     return (
       <Result

+ 3 - 3
src/routes/Forms/StepForm/index.js

@@ -1,4 +1,4 @@
-import React, { PureComponent } from 'react';
+import React, { PureComponent, Fragment } from 'react';
 import { Route, Redirect, Switch } from 'dva/router';
 import { Card, Steps } from 'antd';
 import PageHeaderLayout from '../../../layouts/PageHeaderLayout';
@@ -24,7 +24,7 @@ export default class StepForm extends PureComponent {
     return (
       <PageHeaderLayout title="分步表单" content="将一个冗长或用户不熟悉的表单任务分成多个步骤,指导用户完成。">
         <Card bordered={false}>
-          <div>
+          <Fragment>
             <Steps current={this.getCurrentStep()} className={styles.steps}>
               <Step title="填写转账信息" />
               <Step title="确认转账信息" />
@@ -44,7 +44,7 @@ export default class StepForm extends PureComponent {
               <Redirect exact from="/form/step-form" to="/form/step-form/info" />
               <Redirect to="/exception/404" />
             </Switch>
-          </div>
+          </Fragment>
         </Card>
       </PageHeaderLayout>
     );

+ 3 - 3
src/routes/Forms/TableForm.js

@@ -1,4 +1,4 @@
-import React, { PureComponent } from 'react';
+import React, { PureComponent, Fragment } from 'react';
 import { Table, Button, Input, message, Popconfirm, Divider } from 'antd';
 import styles from './style.less';
 
@@ -203,7 +203,7 @@ export default class TableForm extends PureComponent {
     }];
 
     return (
-      <div>
+      <Fragment>
         <Table
           loading={this.state.loading}
           columns={columns}
@@ -221,7 +221,7 @@ export default class TableForm extends PureComponent {
         >
           新增成员
         </Button>
-      </div>
+      </Fragment>
     );
   }
 }

+ 3 - 3
src/routes/List/Articles.js

@@ -1,4 +1,4 @@
-import React, { Component } from 'react';
+import React, { Component, Fragment } from 'react';
 import moment from 'moment';
 import { connect } from 'dva';
 import { Form, Card, Select, List, Tag, Icon, Avatar, Row, Col, Button } from 'antd';
@@ -99,7 +99,7 @@ export default class SearchList extends Component {
     ) : null;
 
     return (
-      <div>
+      <Fragment>
         <Card bordered={false}>
           <Form layout="inline">
             <StandardFormRow title="所属类目" block style={{ paddingBottom: 11 }}>
@@ -230,7 +230,7 @@ export default class SearchList extends Component {
             )}
           />
         </Card>
-      </div>
+      </Fragment>
     );
   }
 }

+ 7 - 7
src/routes/Profile/AdvancedProfile.js

@@ -1,4 +1,4 @@
-import React, { Component } from 'react';
+import React, { Component, Fragment } from 'react';
 import Debounce from 'lodash-decorators/debounce';
 import Bind from 'lodash-decorators/bind';
 import { connect } from 'dva';
@@ -23,7 +23,7 @@ const menu = (
 );
 
 const action = (
-  <div>
+  <Fragment>
     <ButtonGroup>
       <Button>操作</Button>
       <Button>操作</Button>
@@ -32,7 +32,7 @@ const action = (
       </Dropdown>
     </ButtonGroup>
     <Button type="primary">主操作</Button>
-  </div>
+  </Fragment>
 );
 
 const extra = (
@@ -69,20 +69,20 @@ const tabList = [{
 
 const desc1 = (
   <div className={classNames(styles.textSecondary, styles.stepDescription)}>
-    <div>
+    <Fragment>
       曲丽丽
       <Icon type="dingding-o" style={{ marginLeft: 8 }} />
-    </div>
+    </Fragment>
     <div>2016-12-12 12:32</div>
   </div>
 );
 
 const desc2 = (
   <div className={styles.stepDescription}>
-    <div>
+    <Fragment>
       周毛毛
       <Icon type="dingding-o" style={{ color: '#00A0E9', marginLeft: 8 }} />
-    </div>
+    </Fragment>
     <div><a href="">催一下</a></div>
   </div>
 );

+ 3 - 3
src/routes/Result/Error.js

@@ -1,10 +1,10 @@
-import React from 'react';
+import React, { Fragment } from 'react';
 import { Button, Icon, Card } from 'antd';
 import Result from '../../components/Result';
 import PageHeaderLayout from '../../layouts/PageHeaderLayout';
 
 const extra = (
-  <div>
+  <Fragment>
     <div style={{ fontSize: 16, color: 'rgba(0, 0, 0, 0.85)', fontWeight: '500', marginBottom: 16 }}>
       您提交的内容有如下错误:
     </div>
@@ -16,7 +16,7 @@ const extra = (
       <Icon style={{ color: '#f5222d', marginRight: 8 }} type="close-circle-o" />您的账户还不具备申请资格
       <a style={{ marginLeft: 16 }}>立即升级 <Icon type="right" /></a>
     </div>
-  </div>
+  </Fragment>
 );
 
 const actions = <Button type="primary">返回修改</Button>;

+ 5 - 5
src/routes/Result/Success.js

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { Fragment } from 'react';
 import { Button, Row, Col, Icon, Steps, Card } from 'antd';
 import Result from '../../components/Result';
 import PageHeaderLayout from '../../layouts/PageHeaderLayout';
@@ -24,7 +24,7 @@ const desc2 = (
 );
 
 const extra = (
-  <div>
+  <Fragment>
     <div style={{ fontSize: 16, color: 'rgba(0, 0, 0, 0.85)', fontWeight: '500', marginBottom: 20 }}>
       项目名称
     </div>
@@ -48,15 +48,15 @@ const extra = (
       <Step title={<span style={{ fontSize: 14 }}>财务复核</span>} />
       <Step title={<span style={{ fontSize: 14 }}>完成</span>} />
     </Steps>
-  </div>
+  </Fragment>
 );
 
 const actions = (
-  <div>
+  <Fragment>
     <Button type="primary">返回列表</Button>
     <Button>查看项目</Button>
     <Button>打 印</Button>
-  </div>
+  </Fragment>
 );
 
 export default () => (

+ 23 - 14
src/utils/request.js

@@ -4,21 +4,21 @@ import { routerRedux } from 'dva/router';
 import store from '../index';
 
 const codeMessage = {
-  200: '服务器成功返回请求的数据',
+  200: '服务器成功返回请求的数据',
   201: '新建或修改数据成功。',
-  202: '一个请求已经进入后台排队(异步任务)',
+  202: '一个请求已经进入后台排队(异步任务)',
   204: '删除数据成功。',
-  400: '发出的请求有错误,服务器没有进行新建或修改数据,的操作。',
+  400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
   401: '用户没有权限(令牌、用户名、密码错误)。',
   403: '用户得到授权,但是访问是被禁止的。',
-  404: '发出的请求针对的是不存在的记录,服务器没有进行操作',
+  404: '发出的请求针对的是不存在的记录,服务器没有进行操作',
   406: '请求的格式不可得。',
   410: '请求的资源被永久删除,且不会再得到的。',
   422: '当创建一个对象时,发生一个验证错误。',
-  500: '服务器发生错误,请检查服务器',
-  502: '网关错误',
-  503: '服务不可用,服务器暂时过载或维护',
-  504: '网关超时',
+  500: '服务器发生错误,请检查服务器',
+  502: '网关错误',
+  503: '服务不可用,服务器暂时过载或维护',
+  504: '网关超时',
 };
 function checkStatus(response) {
   if (response.status >= 200 && response.status < 300) {
@@ -48,12 +48,21 @@ export default function request(url, options) {
   };
   const newOptions = { ...defaultOptions, ...options };
   if (newOptions.method === 'POST' || newOptions.method === 'PUT') {
-    newOptions.headers = {
-      Accept: 'application/json',
-      'Content-Type': 'application/json; charset=utf-8',
-      ...newOptions.headers,
-    };
-    newOptions.body = JSON.stringify(newOptions.body);
+    if (!(newOptions.body instanceof FormData)) {
+      newOptions.headers = {
+        Accept: 'application/json',
+        'Content-Type': 'application/json; charset=utf-8',
+        ...newOptions.headers,
+      };
+      newOptions.body = JSON.stringify(newOptions.body);
+    } else {
+      // newOptions.body is FormData
+      newOptions.headers = {
+        Accept: 'application/json',
+        'Content-Type': 'multipart/form-data',
+        ...newOptions.headers,
+      };
+    }
   }
 
   return fetch(url, newOptions)