Explorar o código

Merge branch 'master' of https://github.com/ant-design/test2

ddcat1115 %!s(int64=8) %!d(string=hai) anos
pai
achega
6facbbea1e
Modificáronse 52 ficheiros con 396 adicións e 176 borrados
  1. 1 1
      mock/chart.js
  2. 2 2
      mock/notices.js
  3. 18 0
      src/components/AvatarList/demo/simple.md
  4. 25 0
      src/components/AvatarList/index.md
  5. 3 3
      src/components/Charts/MiniProgress/index.js
  6. 2 0
      src/components/Charts/demo/bar.md
  7. 2 0
      src/components/Charts/demo/gauge.md
  8. 1 0
      src/components/Charts/demo/mini-area.md
  9. 3 0
      src/components/Charts/demo/mini-bar.md
  10. 2 0
      src/components/Charts/demo/mini-pie.md
  11. 4 4
      src/components/Charts/demo/mix.md
  12. 25 0
      src/components/Charts/demo/tag-cloud.md
  13. 27 0
      src/components/Charts/demo/timeline-chart.md
  14. 2 0
      src/components/Charts/demo/waterwave.md
  15. 18 4
      src/components/Charts/index.md
  16. 3 3
      src/components/CountDown/demo/simple.md
  17. 2 2
      src/components/CountDown/index.js
  18. 9 5
      src/components/NoticeIcon/NoticeList.js
  19. 8 12
      src/components/NoticeIcon/NoticeList.less
  20. 18 3
      src/components/NoticeIcon/demo/popover.md
  21. 2 0
      src/components/NoticeIcon/index.js
  22. 4 1
      src/components/NoticeIcon/index.less
  23. 2 0
      src/components/NoticeIcon/index.md
  24. 1 1
      src/components/PageHeader/index.less
  25. 4 4
      src/components/Result/index.less
  26. 1 1
      src/components/StandardFormRow/index.less
  27. 2 2
      src/components/TagSelect/demo/simple.md
  28. 23 21
      src/components/TagSelect/index.js
  29. 9 0
      src/components/TagSelect/index.less
  30. 33 15
      src/layouts/BasicLayout.js
  31. 16 11
      src/layouts/BasicLayout.less
  32. 7 0
      src/models/global.js
  33. 9 0
      src/models/user.js
  34. 3 3
      src/routes/Dashboard.js
  35. 2 2
      src/routes/Dashboard/Workplace.js
  36. 1 1
      src/routes/Forms/AdvancedForm.js
  37. 2 2
      src/routes/Forms/BasicForm.js
  38. 1 1
      src/routes/Forms/StepForm/Step1.js
  39. 19 8
      src/routes/Forms/StepForm/style.less
  40. 40 15
      src/routes/Forms/TableForm.js
  41. 16 17
      src/routes/Forms/style.less
  42. 4 4
      src/routes/List/CardList.js
  43. 1 1
      src/routes/List/CardList.less
  44. 1 1
      src/routes/List/CoverCardList.js
  45. 3 1
      src/routes/List/FilterCardList.js
  46. 6 2
      src/routes/List/FilterCardList.less
  47. 1 1
      src/routes/List/SearchList.js
  48. 3 3
      src/routes/Profile/AdvancedProfile.js
  49. 0 7
      src/routes/Profile/AdvancedProfile.less
  50. 3 3
      src/routes/Profile/BasicProfile.js
  51. 1 9
      src/routes/Profile/BasicProfile.less
  52. 1 0
      src/theme.js

+ 1 - 1
mock/chart.js

@@ -3,7 +3,7 @@ import moment from 'moment';
 // mock data
 const visitData = [];
 const beginDay = new Date().getTime();
-for (let i = 0; i < 7; i += 1) {
+for (let i = 0; i < 30; i += 1) {
   visitData.push({
     x: moment(new Date(beginDay + (1000 * 60 * 60 * 24 * i))).format('YYYY-MM-DD'),
     y: Math.floor(Math.random() * 100) + 10,

+ 2 - 2
mock/notices.js

@@ -56,8 +56,8 @@ export default {
       id: '000000009',
       title: '任务名称',
       description: '任务需要在 2017-01-12 20:00 前启动',
-      extra: '马上到期',
-      status: 'urgent',
+      extra: '未开始',
+      status: 'todo',
       type: '待办',
     }, {
       id: '000000010',

+ 18 - 0
src/components/AvatarList/demo/simple.md

@@ -0,0 +1,18 @@
+---
+order: 0
+title: 基础样例 
+---
+
+简单的用户头像列表。
+
+````jsx
+import AvatarList from 'ant-design-pro/lib/AvatarList';
+
+ReactDOM.render(
+  <AvatarList size="small">
+    <AvatarList.Item tips="Jake" src="https://gw.alipayobjects.com/zos/rmsportal/ZiESqWwCXBRQoaPONSJe.png" />
+    <AvatarList.Item tips="Andy" src="https://gw.alipayobjects.com/zos/rmsportal/tBOxZPlITHqwlGjsJWaF.png" />
+    <AvatarList.Item tips="Niko" src="https://gw.alipayobjects.com/zos/rmsportal/sBxjgqiuHMGRkIjqlQCd.png" />
+  </AvatarList>
+, mountNode);
+````

+ 25 - 0
src/components/AvatarList/index.md

@@ -0,0 +1,25 @@
+---
+category: Components
+type: General
+title: AvatarList 
+subtitle: 用户头像列表
+cols: 1
+---
+
+倒计时组件。
+
+## API
+
+### AvatarList
+
+| 参数      | 说明                                      | 类型         | 默认值 |
+|----------|------------------------------------------|-------------|-------|
+| size | 头像大小 | `large`、`small` | - |
+
+### AvatarList.Item
+
+| 参数      | 说明                                      | 类型         | 默认值 |
+|----------|------------------------------------------|-------------|-------|
+| tips | 头像展示文案 | ReactNode\/string | - |
+| src | 头像图片连接 | string | - |
+

+ 3 - 3
src/components/Charts/MiniProgress/index.js

@@ -1,11 +1,11 @@
 import React from 'react';
-import { Popover } from 'antd';
+import { Tooltip } from 'antd';
 
 import styles from './index.less';
 
 const MiniProgress = ({ target, color, strokeWidth, percent }) => (
   <div className={styles.miniProgress}>
-    <Popover title={null} content={`目标值: ${target}%`}>
+    <Tooltip title={`目标值: ${target}%`}>
       <div
         className={styles.target}
         style={{ left: (target ? `${target}%` : null) }}
@@ -13,7 +13,7 @@ const MiniProgress = ({ target, color, strokeWidth, percent }) => (
         <span style={{ backgroundColor: (color || null) }} />
         <span style={{ backgroundColor: (color || null) }} />
       </div>
-    </Popover>
+    </Tooltip>
     <div className={styles.progressWrap}>
       <div
         className={styles.progress}

+ 2 - 0
src/components/Charts/demo/bar.md

@@ -3,6 +3,8 @@ order: 4
 title: 柱状图
 ---
 
+通过设置 `x`,`y` 属性,可以快速的构建出一个漂亮的柱状图,各种纬度的关系则是通过自定义的数据展现。
+
 ````jsx
 import { Bar } from 'ant-design-pro/lib/Charts';
 

+ 2 - 0
src/components/Charts/demo/gauge.md

@@ -3,6 +3,8 @@ order: 7
 title: 仪表盘 
 ---
 
+仪表盘是一种进度展示方式,可以更直观的展示当前的进展情况,通常也可表示占比。
+
 ````jsx
 import { Gauge } from 'ant-design-pro/lib/Charts';
 

+ 1 - 0
src/components/Charts/demo/mini-area.md

@@ -1,5 +1,6 @@
 ---
 order: 2
+col: 2
 title: 迷你区域图
 ---
 

+ 3 - 0
src/components/Charts/demo/mini-bar.md

@@ -1,8 +1,11 @@
 ---
 order: 2
+col: 2
 title: 迷你柱状图
 ---
 
+迷你柱状图更适合展示简单的区间数据,简洁的表现方式可以很好的减少大数据量的视觉展现压力。
+
 ````jsx
 import { MiniBar } from 'ant-design-pro/lib/Charts';
 import moment from 'moment';

+ 2 - 0
src/components/Charts/demo/mini-pie.md

@@ -3,6 +3,8 @@ order: 6
 title: 迷你饼状图
 ---
 
+通过简化 `Pie` 属性的设置,可以快速的实现极简的饼状图,可配合 `ChartCard` 组合展现更多业务场景。
+
 ````jsx
 import { Pie } from 'ant-design-pro/lib/Charts';
 

+ 4 - 4
src/components/Charts/demo/mix.md

@@ -21,8 +21,8 @@ for (let i = 0; i < 20; i += 1) {
 }
 
 ReactDOM.render(
-  <Row gutter={16}>
-    <Col span={8}>
+  <Row>
+    <Col span={24}>
       <ChartCard
         title="搜索用户数量"
         contentHeight={134}
@@ -41,7 +41,7 @@ ReactDOM.render(
         />
       </ChartCard>
     </Col>  
-    <Col span={8}>
+    <Col span={24} style={{ marginTop: 24 }}>
       <ChartCard
         title="访问量"
         action={<Tooltip title="访问量是关键指标"><Icon type="exclamation-circle-o" /></Tooltip>}
@@ -55,7 +55,7 @@ ReactDOM.render(
         />
       </ChartCard>
     </Col>  
-    <Col span={8}>
+    <Col span={24} style={{ marginTop: 24 }}>
       <ChartCard
         title="线上购物转化率"
         action={<Tooltip title="购买效率"><Icon type="exclamation-circle-o" /></Tooltip>}

+ 25 - 0
src/components/Charts/demo/tag-cloud.md

@@ -0,0 +1,25 @@
+---
+order: 9
+title: 标签云
+---
+
+标签云是一套相关的标签以及与此相应的权重展示方式,一般典型的标签云有 30 至 150 个标签,而权重影响使用的字体大小或其他视觉效果。
+
+````jsx
+import { TagCloud } from 'ant-design-pro/lib/Charts';
+
+const tags = [];
+for (let i = 0; i < 50; i += 1) {
+  tags.push({
+    name: `test-${i}`,
+    value: Math.floor((Math.random() * 50)) + 20,
+  });
+}
+
+ReactDOM.render(
+  <TagCloud
+    data={tags}
+    height={200}
+  />
+, mountNode);
+````

+ 27 - 0
src/components/Charts/demo/timeline-chart.md

@@ -0,0 +1,27 @@
+---
+order: 9
+title: 带有时间轴的图表
+---
+
+使用 `TimelineChart` 组件可以实现带有时间轴的柱状图展现,而其中的 `x` 属性,则是时间值的指向,默认最多支持同时展现两个指标,分别是 `y1` 和 `y2`。
+
+````jsx
+import { TimelineChart } from 'ant-design-pro/lib/Charts';
+
+const chartData = [];
+for (let i = 0; i < 20; i += 1) {
+  chartData.push({
+    x: (new Date().getTime()) + (1000 * 60 * 30 * i),
+    y1: Math.floor(Math.random() * 100) + 10,
+    y2: Math.floor(Math.random() * 100) + 10,
+  });
+}
+
+ReactDOM.render(
+  <TimelineChart
+    height={200}
+    data={chartData}
+    titleMap={{ y1: '客流量', y2: '支付笔数' }}
+  />
+, mountNode);
+````

+ 2 - 0
src/components/Charts/demo/waterwave.md

@@ -3,6 +3,8 @@ order: 8
 title: 水波图 
 ---
 
+水波图是一种比例的展示方式,可以更直观的展示关键值的占比。
+
 ````jsx
 import { WaterWave } from 'ant-design-pro/lib/Charts';
 

+ 18 - 4
src/components/Charts/index.md

@@ -2,12 +2,12 @@
 type: General
 title: Charts
 subtitle: 图表
-cols: 1
+cols: 2
 ---
 
 Ant Design Pro 提供的业务中常用的图表类型,都是基于 [G2](https://antv.alipay.com/g2/doc/index.html) 按照 Ant Design 图表规范封装,需要注意的是 Ant Design Pro 的图表组件以套件形式提供,可以任意组合实现复杂的业务需求。
 
-因为结合了 Ant Design 的标准设计,简化了大量 API 配置,所以如果需要灵活定制图表,可以参考 Ant Design Pro 图表实现,自行基于 [G2](https://antv.alipay.com/g2/doc/index.html) 封装图表组件使用。 
+因为结合了 Ant Design 的标准设计,本着极简的设计思想以及开箱即用的理念,简化了大量 API 配置,所以如果需要灵活定制图表,可以参考 Ant Design Pro 图表实现,自行基于 [G2](https://antv.alipay.com/g2/doc/index.html) 封装图表组件使用。 
 
 ## API
 
@@ -34,6 +34,7 @@ Ant Design Pro 提供的业务中常用的图表类型,都是基于 [G2](https
 | 参数      | 说明                                      | 类型         | 默认值 |
 |----------|------------------------------------------|-------------|-------|
 | color | 图表颜色 | string | `#33abfb` |
+| borderColor | 图表边颜色 | string | `#33abfb` |
 | height | 图表高度 | number | - |
 | line | 是否显示描边 | boolean | false |
 | animate | 是否显示动画 | boolean | true |
@@ -103,6 +104,21 @@ Ant Design Pro 提供的业务中常用的图表类型,都是基于 [G2](https
 | color | 图表颜色 | string | `#19AFFA` |
 | percent | 进度比例 | number | - |
 
+### TagCloud
+
+| 参数      | 说明                                      | 类型         | 默认值 |
+|----------|------------------------------------------|-------------|-------|
+| tags | 标题 | Array<name, value\> | - |
+| height | 高度值 | number | - |
+
+### TimelineChart
+
+| 参数      | 说明                                      | 类型         | 默认值 |
+|----------|------------------------------------------|-------------|-------|
+| data | 标题 | Array<x, y1, y2\> | - |
+| titleMap | 指标别名 | Object{y1: '客流量', y2: '支付笔数'} | - |
+| height | 高度值 | number | 400 |
+
 ### Trend
 
 | 参数      | 说明                                      | 类型         | 默认值 |
@@ -126,5 +142,3 @@ Ant Design Pro 提供的业务中常用的图表类型,都是基于 [G2](https
 |----------|------------------------------------------|-------------|-------|
 | label | 标题 | ReactNode\|string | - |
 | value | 值 | ReactNode\|string | - |
-
-

+ 3 - 3
src/components/CountDown/demo/simple.md

@@ -1,9 +1,9 @@
 ---
 order: 0
-title: Simple
+title: 基础样例 
 ---
 
-简单的页头
+简单的倒计时组件使用
 
 ````jsx
 import CountDown from 'ant-design-pro/lib/CountDown';
@@ -11,6 +11,6 @@ import CountDown from 'ant-design-pro/lib/CountDown';
 const targetTime = new Date().getTime() + 3900000;
 
 ReactDOM.render(
-  <CountDown target={targetTime} />
+  <CountDown style={{ fontSize: 20 }} target={targetTime} />
 , mountNode);
 ````

+ 2 - 2
src/components/CountDown/index.js

@@ -93,12 +93,12 @@ class CountDown extends Component {
   }
 
   render() {
-    const { format = this.defaultFormat } = this.props;
+    const { format = this.defaultFormat, ...rest } = this.props;
     const { lastTime } = this.state;
 
     const result = format(lastTime);
 
-    return result;
+    return (<span {...rest}>{result}</span>);
   }
 }
 

+ 9 - 5
src/components/NoticeIcon/NoticeList.js

@@ -1,14 +1,18 @@
 import React from 'react';
-import { Avatar, Icon, List } from 'antd';
+import { Avatar, List } from 'antd';
 import classNames from 'classnames';
 import styles from './NoticeList.less';
 
-export default function NoticeList({ data = [], onClick, onClear, title, locale }) {
+export default function NoticeList({
+  data = [], onClick, onClear, title, locale, emptyText, emptyImage,
+}) {
   if (data.length === 0) {
     return (
       <div className={styles.notFound}>
-        <Icon type="frown-o" />
-        {locale.emptyText}
+        {emptyImage ? (
+          <img src={emptyImage} alt="not found" />
+        ) : null}
+        <div>{emptyText || locale.emptyText}</div>
       </div>
     );
   }
@@ -25,7 +29,7 @@ export default function NoticeList({ data = [], onClick, onClear, title, locale
                 className={styles.meta}
                 avatar={item.avatar ? <Avatar className={styles.avatar} src={item.avatar} /> : null}
                 title={
-                  <div>
+                  <div className={styles.title}>
                     {item.title}
                     <div className={styles.extra}>{item.extra}</div>
                   </div>

+ 8 - 12
src/components/NoticeIcon/NoticeList.less

@@ -16,6 +16,7 @@
 
     .avatar {
       background: #fff;
+      margin-top: 4px;
     }
 
     &.read {
@@ -29,10 +30,7 @@
     }
     .title {
       font-weight: normal;
-      color: @text-color;
-      overflow: hidden;
-      text-overflow: ellipsis;
-      white-space: nowrap;
+      margin-bottom: 8px;
     }
     .description {
       font-size: 12px;
@@ -48,21 +46,19 @@
       color: @text-color-secondary;
       font-weight: normal;
       margin-right: 0;
+      margin-top: -1.5px;
     }
   }
 }
 
 .notFound {
   text-align: center;
-  height: 120px;
-  line-height: 120px;
-  font-size: 14px;
+  padding: 73px 0 88px 0;
   color: @text-color-secondary;
-  > i {
-    font-size: 16px;
-    margin-right: 8px;
-    vertical-align: middle;
-    margin-top: -1px;
+  img {
+    display: inline-block;
+    margin-bottom: 16px;
+    height: 76px;
   }
 }
 

+ 18 - 3
src/components/NoticeIcon/demo/popover.md

@@ -51,9 +51,24 @@ ReactDOM.render(
     }}
   >
     <NoticeIcon count={5} onItemClick={onItemClick} onClear={onClear}>
-      <NoticeIcon.Tab list={data} title="通知" />
-      <NoticeIcon.Tab list={data} title="消息" />
-      <NoticeIcon.Tab list={[]} title="待办" />
+      <NoticeIcon.Tab
+        list={noticeData['通知']}
+        title="通知"
+        emptyText="你已查看所有通知"
+        emptyImage="https://gw.alipayobjects.com/zos/rmsportal/wAhyIChODzsoKIOBHcBk.svg"
+      />
+      <NoticeIcon.Tab
+        list={noticeData['消息']}
+        title="消息"
+        emptyText="您已读完所有消息"
+        emptyImage="https://gw.alipayobjects.com/zos/rmsportal/sAuJeJzSKbUmHfBQRzmZ.svg"
+      />
+      <NoticeIcon.Tab
+        list={noticeData['待办']}
+        title="待办"
+        emptyText="你已完成所有待办"
+        emptyImage="https://gw.alipayobjects.com/zos/rmsportal/HsIsxMZiWKrNUavQUXqx.svg"
+      />
     </NoticeIcon>
   </div>
 , mountNode);

+ 2 - 0
src/components/NoticeIcon/index.js

@@ -17,6 +17,7 @@ export default class NoticeIcon extends PureComponent {
       emptyText: '暂无数据',
       clear: '清空',
     },
+    emptyImage: 'https://gw.alipayobjects.com/zos/rmsportal/wAhyIChODzsoKIOBHcBk.svg',
   };
   static Tab = TabPane;
   constructor(props) {
@@ -45,6 +46,7 @@ export default class NoticeIcon extends PureComponent {
       return (
         <TabPane tab={title} key={child.props.title}>
           <List
+            {...child.props}
             data={child.props.list}
             onClick={item => this.onItemClick(item, child.props)}
             onClear={() => this.props.onClear(child.props.title)}

+ 4 - 1
src/components/NoticeIcon/index.less

@@ -20,11 +20,14 @@
 
 .tabs {
   :global {
+    .ant-tabs-tab-active {
+      font-weight: 500;
+    }
     .ant-tabs-nav-scroll {
       text-align: center;
     }
     .ant-tabs-bar {
-      margin-bottom: 0;
+      margin-bottom: 4px;
     }
   }
 }

+ 2 - 0
src/components/NoticeIcon/index.md

@@ -27,6 +27,8 @@ locale | 默认文案 | Object | `{ emptyText: '暂无数据', clear: '清空' }
 ----|------|-----|------
 title | 消息分类的页签标题 | string | -
 data | 列表数据,格式参照下表 | Array | `[]`
+emptyText | 针对每个 Tab 定制空数据文案 | ReactNode | -
+emptyImage | 针对每个 Tab 定制空数据图片 | string | -
 
 ### Tab data
 

+ 1 - 1
src/components/PageHeader/index.less

@@ -64,7 +64,7 @@
   }
 
   .logo, .content, .extraContent {
-    margin-bottom: 12px;
+    margin-bottom: 16px;
   }
 
   .action, .extraContent {

+ 4 - 4
src/components/Result/index.less

@@ -24,19 +24,19 @@
     color: @heading-color;
     font-weight: 500;
     line-height: 32px;
-    margin-bottom: 16px;
+    margin-bottom: 8px;
   }
 
   .description {
     font-size: 14px;
     color: @text-color-secondary;
-    margin-bottom: 24px;
+    margin-bottom: 16px;
   }
 
   .extra {
     background: #fafafa;
-    padding: 24px 40px;
-    margin-top: 24px;
+    padding: 16px 40px;
+    margin-top: 16px;
     border-radius: @border-radius-sm;
     text-align: left;
   }

+ 1 - 1
src/components/StandardFormRow/index.less

@@ -12,7 +12,7 @@
     }
     .ant-form-item-label label {
       color: @text-color;
-      margin-right: 16px;
+      margin-right: 0;
     }
   }
   .label {

+ 2 - 2
src/components/TagSelect/demo/simple.md

@@ -1,9 +1,9 @@
 ---
 order: 0
-title: Simple
+title: 基础样例 
 ---
 
-简单的页头
+结合 `Tag` 的 `TagSelect` 组件,方便的应用于筛选类目的业务场景中
 
 ````jsx
 import TagSelect from 'ant-design-pro/lib/TagSelect';

+ 23 - 21
src/components/TagSelect/index.js

@@ -123,27 +123,29 @@ class TagSelect extends PureComponent {
 
     return (
       <div className={cls} style={style}>
-        <CheckableTag
-          checked={checkedAll}
-          key="tag-select-__all__"
-          onChange={this.onSelectAll}
-        >
-          全部
-        </CheckableTag>
-        {
-          children.filter(child => child.props.displayName === 'TagSelectOption').map(child => React.cloneElement(child, {
-            key: `tag-select-${child.props.value}`,
-            checked: checkedTags.indexOf(child.props.value) > -1,
-            onChange: this.handleTagChange,
-          }))
-        }
-        {
-          expandNode && (
-            <a className={styles.trigger} onClick={this.handleExpand}>
-              { expand ? '收起' : '展开'} <Icon type={expand ? 'up' : 'down'} />
-            </a>
-          )
-        }
+        <div>
+          <CheckableTag
+            checked={checkedAll}
+            key="tag-select-__all__"
+            onChange={this.onSelectAll}
+          >
+            全部
+          </CheckableTag>
+          {
+            children.filter(child => child.props.displayName === 'TagSelectOption').map(child => React.cloneElement(child, {
+              key: `tag-select-${child.props.value}`,
+              checked: checkedTags.indexOf(child.props.value) > -1,
+              onChange: this.handleTagChange,
+            }))
+          }
+          {
+            expandNode && (
+              <a className={styles.trigger} onClick={this.handleExpand}>
+                { expand ? '收起' : '展开'} <Icon type={expand ? 'up' : 'down'} />
+              </a>
+            )
+          }
+        </div>
         {
           expandNode && (
             <div className={expand ? styles.expand : styles.fold}>

+ 9 - 0
src/components/TagSelect/index.less

@@ -5,6 +5,12 @@
   user-select: none;
   margin-left: -8px;
   position: relative;
+  :global {
+    .ant-tag {
+      padding: 0 8px;
+      margin-right: 24px;
+    }
+  }
   .expand {
     transition: all 0.32s ease;
     overflow: hidden;
@@ -18,6 +24,9 @@
     position: absolute;
     top: 0;
     right: 0;
+    i {
+      font-size: 12px;
+    }
   }
 }
 .expandTag {

+ 33 - 15
src/layouts/BasicLayout.js

@@ -1,6 +1,6 @@
 import React from 'react';
 import PropTypes from 'prop-types';
-import { Layout, Menu, Icon, Avatar, Dropdown, Tag, message } from 'antd';
+import { Layout, Menu, Icon, Avatar, Dropdown, Tag, message, Spin } from 'antd';
 import DocumentTitle from 'react-document-title';
 import { connect } from 'dva';
 import { Link, routerRedux } from 'dva/router';
@@ -122,9 +122,10 @@ class BasicLayout extends React.PureComponent {
       }
       if (newNotice.extra && newNotice.status) {
         const color = ({
+          todo: '',
           processing: 'blue',
           urgent: 'red',
-          doing: 'yellow',
+          doing: 'gold',
         })[newNotice.status];
         newNotice.extra = <Tag color={color}>{newNotice.extra}</Tag>;
       }
@@ -164,8 +165,8 @@ class BasicLayout extends React.PureComponent {
 
     const menu = (
       <Menu className={styles.menu} selectedKeys={[]} onClick={this.onMenuClick}>
-        <Menu.Item><Icon type="user" />个人中心</Menu.Item>
-        <Menu.Item><Icon type="setting" />设置</Menu.Item>
+        <Menu.Item disabled><Icon type="user" />个人中心</Menu.Item>
+        <Menu.Item disabled><Icon type="setting" />设置</Menu.Item>
         <Menu.Divider />
         <Menu.Item key="logout"><Icon type="logout" />退出登录</Menu.Item>
       </Menu>
@@ -193,7 +194,7 @@ class BasicLayout extends React.PureComponent {
           >
             <div className={styles.logo}>
               <Link to="/">
-                <img src="https://gw.alipayobjects.com/zos/rmsportal/osjtaBtmmQzWRvMbcKeb.svg" alt="logo" />
+                <img src="https://gw.alipayobjects.com/zos/rmsportal/iwWyPinUoseUxIAeElSx.svg" alt="logo" />
                 <h1>Ant Design Pro</h1>
               </Link>
             </div>
@@ -204,7 +205,7 @@ class BasicLayout extends React.PureComponent {
               onOpenChange={this.handleOpenChange}
               selectedKeys={this.getCurrentMenuSelectedKeys()}
               style={{ margin: '24px 0', width: '100%' }}
-              inlineIndent={32}
+              inlineIndent={24}
             >
               {this.getNavMenuItems(this.menus)}
             </Menu>
@@ -239,16 +240,33 @@ class BasicLayout extends React.PureComponent {
                   loading={fetchingNotices}
                   popupAlign={{ offset: [20, -16] }}
                 >
-                  <NoticeIcon.Tab list={noticeData['通知']} title="通知" />
-                  <NoticeIcon.Tab list={noticeData['消息']} title="消息" />
-                  <NoticeIcon.Tab list={noticeData['待办']} title="待办" />
+                  <NoticeIcon.Tab
+                    list={noticeData['通知']}
+                    title="通知"
+                    emptyText="你已查看所有通知"
+                    emptyImage="https://gw.alipayobjects.com/zos/rmsportal/wAhyIChODzsoKIOBHcBk.svg"
+                  />
+                  <NoticeIcon.Tab
+                    list={noticeData['消息']}
+                    title="消息"
+                    emptyText="您已读完所有消息"
+                    emptyImage="https://gw.alipayobjects.com/zos/rmsportal/sAuJeJzSKbUmHfBQRzmZ.svg"
+                  />
+                  <NoticeIcon.Tab
+                    list={noticeData['待办']}
+                    title="待办"
+                    emptyText="你已完成所有待办"
+                    emptyImage="https://gw.alipayobjects.com/zos/rmsportal/HsIsxMZiWKrNUavQUXqx.svg"
+                  />
                 </NoticeIcon>
-                <Dropdown overlay={menu}>
-                  <span className={`${styles.action} ${styles.account}`}>
-                    <Avatar size="small" className={styles.avatar} src={currentUser.avatar} />
-                    {currentUser.name}
-                  </span>
-                </Dropdown>
+                {currentUser.name ? (
+                  <Dropdown overlay={menu}>
+                    <span className={`${styles.action} ${styles.account}`}>
+                      <Avatar size="small" className={styles.avatar} src={currentUser.avatar} />
+                      {currentUser.name}
+                    </span>
+                  </Dropdown>
+                ) : <Spin size="small" style={{ marginLeft: 8 }} />}
               </div>
             </Header>
             <Content style={{ margin: '24px 24px 0', height: '100%' }}>

+ 16 - 11
src/layouts/BasicLayout.less

@@ -1,7 +1,7 @@
 @import "~antd/lib/style/themes/default.less";
 
 .header {
-  padding: 0 16px 0 0;
+  padding: 0 12px 0 0;
   background: #fff;
   box-shadow: 0 1px 4px rgba(0, 21, 41, .12);
   position: relative;
@@ -13,7 +13,7 @@
   line-height: 64px;
   padding-left: 32px;
   transition: all .3s;
-  background: #00284d;
+  background: #002140;
   overflow: hidden;
   img {
     display: inline-block;
@@ -24,10 +24,11 @@
     color: #fff;
     display: inline-block;
     vertical-align: middle;
-    font-size: 22px;
+    font-size: 18px;
     margin-left: 12px;
     font-family: Lato, 'Helvetica Neue', Arial, Helvetica, sans-serif;
-    margin-top: -2px;
+    margin-top: -3px;
+    font-weight: bold;
   }
 }
 
@@ -43,9 +44,15 @@
   line-height: 64px;
   cursor: pointer;
   transition: all .3s;
-  padding: 0 28px;
+  padding: 0 24px;
   &:hover {
-    background: rgba(0, 0, 0, .04);
+    background: @primary-1;
+  }
+}
+
+@media screen and (max-width: @screen-xs) {
+  .trigger {
+    display: none;
   }
 }
 
@@ -64,7 +71,7 @@
     }
     &:global(.ant-popover-open),
     &:hover {
-      background: rgba(0, 0, 0, .04);
+      background: @primary-1;
     }
   }
   .search {
@@ -89,9 +96,7 @@
     margin-right: 8px;
   }
   :global(.ant-dropdown-menu-item) {
-    padding-left: 16px;
-    padding-right: 16px;
-    width: 190px;
+    width: 160px;
   }
 }
 
@@ -105,5 +110,5 @@
   min-height: 100vh;
   box-shadow: 2px 0 6px rgba(0, 21, 41, .35);
   position: relative;
-  z-index: 1;
+  z-index: 10;
 }

+ 7 - 0
src/models/global.js

@@ -21,6 +21,13 @@ export default {
         payload: data,
       });
     },
+    *clearNotices(_, { put, select }) {
+      const count = yield select(state => state.global.notices.length);
+      yield put({
+        type: 'user/changeNotifyCount',
+        payload: count,
+      });
+    },
   },
 
   reducers: {

+ 9 - 0
src/models/user.js

@@ -53,5 +53,14 @@ export default {
         currentUser: action.payload,
       };
     },
+    changeNotifyCount(state, action) {
+      return {
+        ...state,
+        currentUser: {
+          ...state.currentUser,
+          notifyCount: action.payload,
+        },
+      };
+    },
   },
 };

+ 3 - 3
src/routes/Dashboard.js

@@ -1,6 +1,6 @@
 import React, { PureComponent } from 'react';
 import { connect } from 'dva';
-import { Row, Col, Card, Table, Icon } from 'antd';
+import { Row, Col, Card, Table, Icon, Divider } from 'antd';
 
 const columns = [{
   title: 'Name',
@@ -20,9 +20,9 @@ const columns = [{
   render: (text, record) => (
     <span>
       <a href="">Action 一 {record.name}</a>
-      <span className="ant-divider" />
+      <Divider type="vertical" />
       <a href="">Delete</a>
-      <span className="ant-divider" />
+      <Divider type="vertical" />
       <a href="" className="ant-dropdown-link">
         More actions <Icon type="down" />
       </a>

+ 2 - 2
src/routes/Dashboard/Workplace.js

@@ -109,7 +109,7 @@ export default class Workplace extends PureComponent {
           <Avatar size="large" src="https://gw.alipayobjects.com/zos/rmsportal/XertDCubOxUvZbCdgWTW.png" />
         </div>
         <div className={styles.content}>
-          <p className={styles.contentTitle}>早安, 曲丽丽, 祝你开心每一天</p>
+          <p className={styles.contentTitle}>早安,曲丽丽,祝你开心每一天</p>
           <p>交互专家 | 蚂蚁金服-某某某事业群-某某平台部-某某技术部-UED</p>
         </div>
       </div>
@@ -187,7 +187,7 @@ export default class Workplace extends PureComponent {
                     activitiesList.map(item => (
                       <List.Item key={item.id}>
                         <List.Item.Meta
-                          avatar={<Avatar style={{ marginTop: -12 }} src={item.user.avatar} />}
+                          avatar={<Avatar src={item.user.avatar} />}
                           title={
                             <p>
                               <a>{item.user.name}</a> 在 <a>xx</a> 新建了项目 <a>xxxx</a>

+ 1 - 1
src/routes/Forms/AdvancedForm.js

@@ -97,7 +97,7 @@ function AdvancedForm({ form, dispatch, submitting }) {
     <PageHeaderLayout
       title="高级表单"
       content="在后台页面中,大批量的数据修改和提交是很常见的情况。"
-      wrapperClassName={styles.withFooterToolbar}
+      wrapperClassName={styles.advancedForm}
     >
       <Card title="仓库管理" className={styles.card} bordered={false}>
         <Form layout="vertical" hideRequiredMark>

+ 2 - 2
src/routes/Forms/BasicForm.js

@@ -162,7 +162,7 @@ export default class BasicForms extends PureComponent {
                     mode="multiple"
                     placeholder="公开给"
                     style={{
-                      margin: '12px 0',
+                      margin: '8px 0',
                       display: getFieldValue('public') === '2' ? 'block' : 'none',
                     }}
                   >
@@ -173,7 +173,7 @@ export default class BasicForms extends PureComponent {
                 )}
               </div>
             </FormItem>
-            <FormItem {...submitFormLayout} style={{ marginTop: 40 }}>
+            <FormItem {...submitFormLayout} style={{ marginTop: 32 }}>
               <Button type="primary" htmlType="submit" loading={submitting}>
                 提交
               </Button>

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

@@ -91,7 +91,7 @@ export default ({ formItemLayout, form, dispatch }) => {
           </Button>
         </Form.Item>
       </Form>
-      <Divider style={{ margin: '48px 0 16px' }} />
+      <Divider style={{ margin: '40px 0 24px' }} />
       <div className={styles.desc}>
         <h3>说明</h3>
         <h4>转账到支付宝账户</h4>

+ 19 - 8
src/routes/Forms/StepForm/style.less

@@ -6,6 +6,7 @@
 }
 
 .stepFormText {
+  margin-bottom: 24px;
   :global {
     .ant-form-item-label,
     .ant-form-item-control {
@@ -16,26 +17,36 @@
 
 .result {
   margin: 0 auto;
-  max-width: 520px;
-  padding: 32px 0;
+  max-width: 560px;
+  padding: 24px 0;
 }
 
 .desc {
   h3 {
-    font-size: 14px;
-    margin: 8px 0;
+    font-size: 16px;
+    margin: 0 0 12px 0;
     color: @text-color-secondary;
+    line-height: 32px;
   }
   h4 {
-    margin: 2px 0;
+    margin: 0 0 4px 0;
     color: @text-color-secondary;
+    font-size: 14px;
+    line-height: 22px;
   }
   p {
-    margin-bottom: 16px;
+    margin-top: 0;
+    margin-bottom: 12px;
+    line-height: 22px;
   }
-  padding: 0 34px;
+  padding: 0 80px;
   color: @text-color-secondary;
-  font-size: 12px;
+}
+
+@media screen and (max-width: @screen-md) {
+  .desc {
+    padding: 0;
+  }
 }
 
 .information {

+ 40 - 15
src/routes/Forms/TableForm.js

@@ -1,5 +1,5 @@
 import React, { PureComponent } from 'react';
-import { Table, Button, Input, message } from 'antd';
+import { Table, Button, Input, message, Popconfirm, Divider } from 'antd';
 import styles from './style.less';
 
 export default class TableForm extends PureComponent {
@@ -45,8 +45,7 @@ export default class TableForm extends PureComponent {
       this.setState({ data: [...this.state.data] });
     }
   }
-  remove(e, key) {
-    e.preventDefault();
+  remove(key) {
     const newData = this.state.data.filter(item => item.key !== key);
     this.setState({ data: newData });
     this.props.onChange(newData);
@@ -64,6 +63,11 @@ export default class TableForm extends PureComponent {
     this.index += 1;
     this.setState({ data: newData });
   }
+  handleKeyPress(e, key) {
+    if (e.key === 'Enter') {
+      this.saveRow(e, key);
+    }
+  }
   handleFieldChange(e, fieldName, key) {
     const newData = [...this.state.data];
     const target = this.getRowByKey(key);
@@ -73,16 +77,29 @@ export default class TableForm extends PureComponent {
     }
   }
   saveRow(e, key) {
-    const target = this.getRowByKey(key);
-    delete target.isNew;
-    if (!target.workId || !target.name || !target.department) {
-      message.error('请填写完整成员信息。');
-      return;
-    }
-    this.toggleEditable(e, key);
-    this.props.onChange(this.state.data);
+    e.persist();
+    // save field when blur input
+    setTimeout(() => {
+      if (document.activeElement.tagName === 'INPUT' &&
+          document.activeElement !== e.target) {
+        return;
+      }
+      if (this.clickedCancel) {
+        this.clickedCancel = false;
+        return;
+      }
+      const target = this.getRowByKey(key);
+      delete target.isNew;
+      if (!target.workId || !target.name || !target.department) {
+        message.error('请填写完整成员信息。');
+        return;
+      }
+      this.toggleEditable(e, key);
+      this.props.onChange(this.state.data);
+    }, 10);
   }
   cancel(e, key) {
+    this.clickedCancel = true;
     e.preventDefault();
     const target = this.getRowByKey(key);
     if (this.cacheOriginData[key]) {
@@ -105,6 +122,8 @@ export default class TableForm extends PureComponent {
               value={text}
               autoFocus
               onChange={e => this.handleFieldChange(e, 'name', record.key)}
+              onBlur={e => this.saveRow(e, record.key)}
+              onKeyPress={e => this.handleKeyPress(e, record.key)}
               placeholder="成员姓名"
             />
           );
@@ -122,6 +141,8 @@ export default class TableForm extends PureComponent {
             <Input
               value={text}
               onChange={e => this.handleFieldChange(e, 'workId', record.key)}
+              onBlur={e => this.saveRow(e, record.key)}
+              onKeyPress={e => this.handleKeyPress(e, record.key)}
               placeholder="工号"
             />
           );
@@ -139,6 +160,8 @@ export default class TableForm extends PureComponent {
             <Input
               value={text}
               onChange={e => this.handleFieldChange(e, 'department', record.key)}
+              onBlur={e => this.saveRow(e, record.key)}
+              onKeyPress={e => this.handleKeyPress(e, record.key)}
               placeholder="所属部门"
             />
           );
@@ -154,7 +177,7 @@ export default class TableForm extends PureComponent {
             return (
               <span>
                 <a onClick={e => this.saveRow(e, record.key)}>保存</a>
-                <span className="ant-divider" />
+                <Divider type="vertical" />
                 <a onClick={e => this.remove(e, record.key)}>删除</a>
               </span>
             );
@@ -162,7 +185,7 @@ export default class TableForm extends PureComponent {
           return (
             <span>
               <a onClick={e => this.saveRow(e, record.key)}>保存</a>
-              <span className="ant-divider" />
+              <Divider type="vertical" />
               <a onClick={e => this.cancel(e, record.key)}>取消</a>
             </span>
           );
@@ -170,8 +193,10 @@ export default class TableForm extends PureComponent {
         return (
           <span>
             <a onClick={e => this.toggleEditable(e, record.key)}>编辑</a>
-            <span className="ant-divider" />
-            <a onClick={e => this.remove(e, record.key)}>删除</a>
+            <Divider type="vertical" />
+            <Popconfirm title="是否要删除此行?" onConfirm={() => this.remove(record.key)}>
+              <a>删除</a>
+            </Popconfirm>
           </span>
         );
       },

+ 16 - 17
src/routes/Forms/style.less

@@ -15,13 +15,6 @@
   margin: 16px auto;
 }
 
-.divider {
-  border: 0;
-  border-top: 1px solid @border-color-split;
-  height: 1px;
-  margin: 0 0 24px 0;
-}
-
 .errorIcon {
   cursor: pointer;
   color: @error-color;
@@ -37,7 +30,7 @@
       padding: 0;
       max-height: 290px;
       overflow: auto;
-      min-width: 240px;
+      min-width: 256px;
     }
   }
 }
@@ -45,7 +38,7 @@
 .errorListItem {
   list-style: none;
   border-bottom: 1px solid @border-color-split;
-  padding: 8px 24px;
+  padding: 8px 16px;
   cursor: pointer;
   transition: all .3s;
   &:hover {
@@ -58,21 +51,16 @@
     color: @error-color;
     float: left;
     margin-top: 4px;
-    margin-right: 8px;
+    margin-right: 12px;
     padding-bottom: 22px;
   }
   .errorField {
     font-size: 12px;
     color: @text-color-secondary;
-    margin-top: 4px;
+    margin-top: 2px;
   }
 }
 
-// 避免表格编辑模式切换时抖动
-:global(.ant-table) td {
-  transition: none !important;
-}
-
 .editable {
   td {
     padding-top: 13px !important;
@@ -81,10 +69,21 @@
 }
 
 // custom footer for fixed footer toolbar
-.withFooterToolbar + div {
+.advancedForm + div {
   padding-bottom: 64px;
 }
 
+.advancedForm {
+  :global {
+    .ant-form .ant-row:last-child .ant-form-item {
+      margin-bottom: 24px;
+    }
+    .ant-table td {
+      transition: none !important;
+    }
+  }
+}
+
 .optional {
   color: @text-color-secondary;
   font-style: normal;

+ 4 - 4
src/routes/List/CardList.js

@@ -62,8 +62,8 @@ export default class CardList extends PureComponent {
             dataSource={['', ...list]}
             renderItem={item => (item ? (
               <List.Item key={item.id}>
-                <Link to="/list/card-list">
-                  <Card hoverable actions={[<a>操作一</a>, <a>操作二</a>]}>
+                <Card hoverable actions={[<a>操作一</a>, <a>操作二</a>]}>
+                  <Link to="/list/card-list">
                     <Card.Meta
                       avatar={<Avatar size="large" src={item.avatar} />}
                       title={item.title}
@@ -73,8 +73,8 @@ export default class CardList extends PureComponent {
                         </p>
                       )}
                     />
-                  </Card>
-                </Link>
+                  </Link>
+                </Card>
               </List.Item>
               ) : (
                 <List.Item>

+ 1 - 1
src/routes/List/CardList.less

@@ -24,7 +24,7 @@
   border-color: @border-color-base;
   color: @text-color-secondary;
   width: 100%;
-  height: 178px;
+  height: 185px;
 }
 
 .cardDescription {

+ 1 - 1
src/routes/List/CoverCardList.js

@@ -153,7 +153,7 @@ export default class CoverCardList extends PureComponent {
         onTabChange={this.handleTabChange}
       >
         <div className={styles.coverCardList}>
-          <Card bordered={false}>
+          <Card bordered={false} bodyStyle={{ padding: 24 }}>
             <Form layout="inline">
               <StandardFormRow title="所属类目" block>
                 <FormItem>

+ 3 - 1
src/routes/List/FilterCardList.js

@@ -151,7 +151,7 @@ export default class FilterCardList extends PureComponent {
         onTabChange={this.handleTabChange}
       >
         <div className={styles.filterCardList}>
-          <Card bordered={false}>
+          <Card bordered={false} bodyStyle={{ padding: 24 }}>
             <Form layout="inline">
               <StandardFormRow title="所属类目" block>
                 <FormItem>
@@ -221,6 +221,8 @@ export default class FilterCardList extends PureComponent {
             renderItem={item => (
               <List.Item key={item.id}>
                 <Card
+                  hoverable
+                  bodyStyle={{ paddingBottom: 16 }}
                   actions={[
                     <Tooltip title="下载"><Icon type="download" /></Tooltip>,
                     <Tooltip title="编辑"><Icon type="edit" /></Tooltip>,

+ 6 - 2
src/routes/List/FilterCardList.less

@@ -7,10 +7,14 @@
     .ant-card-meta-content {
       margin-top: 0;
     }
+    // disabled white space
+    .ant-card-meta-avatar {
+      font-size: 0;
+    }
   }
   .cardInfo {
     .clearfix();
-    margin-top: 12px;
+    margin-top: 16px;
     margin-left: 40px;
     & > div {
       position: relative;
@@ -18,7 +22,7 @@
       float: left;
       width: 50%;
       p {
-        color: @text-color;
+        color: @text-color-secondary;
         line-height: 32px;
         font-size: 24px;
       }

+ 1 - 1
src/routes/List/SearchList.js

@@ -183,7 +183,7 @@ export default class SearchList extends Component {
         onTabChange={this.handleTabChange}
       >
         <div>
-          <Card bordered={false}>
+          <Card bordered={false} bodyStyle={{ padding: 24 }}>
             <Form layout="inline">
               <StandardFormRow title="所属类目" block>
                 <FormItem>

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

@@ -1,6 +1,6 @@
 import React, { Component } from 'react';
 import { connect } from 'dva';
-import { Button, Menu, Dropdown, Icon, Row, Col, Steps, Card, Popover, Badge, Table, Tooltip } from 'antd';
+import { Button, Menu, Dropdown, Icon, Row, Col, Steps, Card, Popover, Badge, Table, Tooltip, Divider } from 'antd';
 import PageHeaderLayout from '../../layouts/PageHeaderLayout';
 import DescriptionList from '../../components/DescriptionList';
 import EditableItem from '../../components/EditableItem';
@@ -229,13 +229,13 @@ export default class AdvancedProfile extends Component {
               <Description term="过期时间">2017-08-08</Description>
               <Description term="描述">这段描述很长很长很长很长很长很长很长很长很长很长很长很长很长很长...</Description>
             </DescriptionList>
-            <div className={styles.divider} />
+            <Divider style={{ marginBottom: 16 }} />
             <DescriptionList style={{ marginBottom: 16 }} title="组名称" col="1">
               <Description term="学名">
                 Citrullus lanatus (Thunb.) Matsum. et Nakai一年生蔓生藤本;茎、枝粗壮,具明显的棱。卷须较粗..
               </Description>
             </DescriptionList>
-            <div className={styles.divider} />
+            <Divider style={{ marginBottom: 16 }} />
             <DescriptionList title="组名称">
               <Description term="负责人">付小小</Description>
               <Description term="角色码">1234568</Description>

+ 0 - 7
src/routes/Profile/AdvancedProfile.less

@@ -18,10 +18,3 @@
 .textSecondary {
   color: @text-color-secondary;
 }
-
-.divider {
-  border: 0;
-  border-top: 1px solid @border-color-split;
-  height: 1px;
-  margin: 0 0 16px 0;
-}

+ 3 - 3
src/routes/Profile/BasicProfile.js

@@ -1,6 +1,6 @@
 import React, { Component } from 'react';
 import { connect } from 'dva';
-import { Card, Badge, Table } from 'antd';
+import { Card, Badge, Table, Divider } from 'antd';
 import PageHeaderLayout from '../../layouts/PageHeaderLayout';
 import DescriptionList from '../../components/DescriptionList';
 import styles from './BasicProfile.less';
@@ -133,7 +133,7 @@ export default class BasicProfile extends Component {
             <Description term="销售单号">1234123421</Description>
             <Description term="子订单">3214321432</Description>
           </DescriptionList>
-          <div className={styles.divider} />
+          <Divider style={{ marginBottom: 32 }} />
           <DescriptionList title="用户信息" style={{ marginBottom: 32 }}>
             <Description term="用户姓名">付小小</Description>
             <Description term="联系电话">18100000000</Description>
@@ -141,7 +141,7 @@ export default class BasicProfile extends Component {
             <Description term="取货地址">浙江省杭州市西湖区万塘路18号</Description>
             <Description term="备注">无</Description>
           </DescriptionList>
-          <div className={styles.divider} />
+          <Divider style={{ marginBottom: 32 }} />
           <div className={styles.title}>退货商品</div>
           <Table
             style={{ marginBottom: 24 }}

+ 1 - 9
src/routes/Profile/BasicProfile.less

@@ -1,14 +1,7 @@
 @import "~antd/lib/style/themes/default.less";
 
-.divider {
-  border: 0;
-  border-top: 1px solid @border-color-split;
-  height: 1px;
-  margin: 0 0 32px 0;
-}
-
 .title {
-  color: rgba(0, 0, 0, 0.85);
+  color: @heading-color;
   font-weight: 500;
   margin-bottom: 16px;
 }
@@ -18,4 +11,3 @@
     text-align: right!important;
   }
 }
-

+ 1 - 0
src/theme.js

@@ -1,4 +1,5 @@
 // https://github.com/ant-design/ant-design/blob/master/components/style/themes/default.less
 module.exports = {
   // 'primary-color': '#10e99b',
+  'card-actions-background': '#f7f9fa',
 };