陈帅 7 rokov pred
rodič
commit
d6860a7203

+ 0 - 47
.webpackrc.js

@@ -1,47 +0,0 @@
-const path = require('path');
-
-export default {
-  entry: 'src/index.js',
-  extraBabelPlugins: [['import', { libraryName: 'antd', libraryDirectory: 'es', style: true }]],
-  env: {
-    development: {
-      extraBabelPlugins: ['dva-hmr'],
-    },
-  },
-  externals: {
-    '@antv/data-set': 'DataSet',
-    bizcharts: 'BizCharts',
-    rollbar: 'rollbar',
-  },
-  alias: {
-    components: path.resolve(__dirname, 'src/components/'),
-  },
-  ignoreMomentLocale: true,
-  theme: './src/theme.js',
-  html: {
-    template: './src/index.ejs',
-  },
-  publicPath: '/',
-  hash: true,
-  lessLoaderOptions: {
-    javascriptEnabled: true,
-  },
-  disableDynamicImport: true,
-  cssLoaderOptions: {
-    modules: true,
-    getLocalIdent: (context, localIdentName, localName) => {
-      if (
-        context.resourcePath.includes('node_modules') ||
-        context.resourcePath.includes('ant.design.pro.less')
-      ) {
-        return localName;
-      }
-      const antdProPath = context.resourcePath.match(/src(.*)/)[1].replace('.less', '');
-      const arr = antdProPath
-        .split('/')
-        .map(a => a.replace(/([A-Z])/g, '-$1'))
-        .map(a => a.toLowerCase());
-      return `antd-pro${arr.join('-')}-${localName}`.replace(/--/g, '-');
-    },
-  },
-};

+ 8 - 1
config/config.js

@@ -9,6 +9,7 @@ export default {
   // add for transfer to umi
   plugins: [
     'umi-plugin-dva',
+    'umi-plugin-locale',
     // TODO 决定是否使用约定路由,如果使用配置路由那么 umi-plugin-routes 可以去掉了
     // [
     //   'umi-plugin-routes',
@@ -21,7 +22,12 @@ export default {
     // ],
   ],
   disableServiceWorker: true,
-
+  locale: {
+    enable: true, // default false
+    default: 'zh-CN', // default zh-CN
+    baseNavigator: true, // default true, when it is true, will use `navigator.language` overwrite default
+    antd: true, // use antd, default is true
+  },
   // 路由配置
   routes: [
     // user
@@ -173,4 +179,5 @@ export default {
       return `antd-pro${arr.join('-')}-${localName}`.replace(/--/g, '-');
     },
   },
+  disableFastClick: true,
 };

+ 5 - 4
package.json

@@ -30,8 +30,8 @@
     "lodash": "^4.17.4",
     "lodash-decorators": "^6.0.0",
     "lodash.isequal": "^4.5.0",
-    "moment": "^2.22.2",
     "memoize-one": "^3.1.1",
+    "moment": "^2.22.2",
     "numeral": "^2.0.6",
     "omit.js": "^1.0.0",
     "path-to-regexp": "^2.1.0",
@@ -42,11 +42,12 @@
     "react-copy-to-clipboard": "^5.0.1",
     "react-document-title": "^2.0.3",
     "react-fittext": "^1.0.0",
-    "react-intl": "^2.4.0",
+    "umi/locale": "^2.4.0",
     "rollbar": "^2.3.4",
     "rollup": "^0.62.0",
     "rollup-plugin-json": "^3.0.0",
     "setprototypeof": "^1.1.0",
+    "umi-plugin-locale": "^1.0.1",
     "url-polyfill": "^1.0.10"
   },
   "devDependencies": {
@@ -84,8 +85,8 @@
     "stylelint-config-prettier": "^3.0.4",
     "stylelint-config-standard": "^18.0.0",
     "umi": "^1.3.13",
-    "umi-plugin-routes": "^0.1.5",
-    "umi-plugin-dva": "^0.9.1"
+    "umi-plugin-dva": "^0.9.1",
+    "umi-plugin-routes": "^0.1.5"
   },
   "optionalDependencies": {
     "puppeteer": "^1.5.0"

+ 0 - 4
src/common/menu.js

@@ -231,13 +231,9 @@ const menuData = [
         path: 'step-form',
       },
       {
-<<<<<<< HEAD
-        name: '高级表单',
         // authority: 'admin',
-=======
         name: 'advancedform',
         authority: 'admin',
->>>>>>> add meun Intl
         path: 'advanced-form',
       },
     ],

+ 11 - 19
src/components/GlobalHeader/RightContent.js

@@ -1,9 +1,8 @@
 import React, { PureComponent } from 'react';
-import { FormattedMessage } from 'react-intl';
+import { FormattedMessage, setLocale, getLocale } from 'umi/locale';
 import { Spin, Tag, Menu, Icon, Dropdown, Avatar, Tooltip, Button } from 'antd';
 import moment from 'moment';
 import groupBy from 'lodash/groupBy';
-import LocaleContext from '../../locale/localeContext';
 import NoticeIcon from '../NoticeIcon';
 import HeaderSearch from '../HeaderSearch';
 import styles from './index.less';
@@ -42,11 +41,11 @@ export default class GlobalHeaderRight extends PureComponent {
   }
 
   changLang = () => {
-    const locale = localStorage.getItem('locale');
+    const locale = getLocale();
     if (!locale || locale === 'zh-CN') {
-      localStorage.setItem('locale', 'en-US');
+      setLocale('en-US');
     } else {
-      localStorage.setItem('locale', 'zh-CN');
+      setLocale('zh-CN');
     }
   };
 
@@ -153,21 +152,14 @@ export default class GlobalHeaderRight extends PureComponent {
         ) : (
           <Spin size="small" style={{ marginLeft: 8, marginRight: 8 }} />
         )}
-        <LocaleContext.Consumer>
-          {context => {
-            return (
-              <Button
-                size="small"
-                onClick={() => {
-                  this.changLang();
-                  context.changeLocal();
-                }}
-              >
-                <FormattedMessage id="navbar.lang" />
-              </Button>
-            );
+        <Button
+          size="small"
+          onClick={() => {
+            this.changLang();
           }}
-        </LocaleContext.Consumer>
+        >
+          <FormattedMessage id="navbar.lang" />
+        </Button>
       </div>
     );
   }

+ 1 - 1
src/components/SiderMenu/BaseMenu.js

@@ -1,7 +1,7 @@
 import React, { PureComponent } from 'react';
 import { Menu, Icon } from 'antd';
 import { Link } from 'dva/router';
-import { FormattedMessage } from 'react-intl';
+import { FormattedMessage } from 'umi/locale';
 import pathToRegexp from 'path-to-regexp';
 import { urlToList } from '../_utils/pathTools';
 import styles from './index.less';

+ 1 - 1
src/components/SiderMenu/SliderMenu.js

@@ -2,7 +2,7 @@ import React, { PureComponent } from 'react';
 import { Layout, Menu, Icon } from 'antd';
 import pathToRegexp from 'path-to-regexp';
 import { Link } from 'dva/router';
-import { FormattedMessage } from 'react-intl';
+import { FormattedMessage } from 'umi/locale';
 import styles from './index.less';
 import BaseMenu, { getMenuMatches } from './BaseMenu';
 import { urlToList } from '../_utils/pathTools';

+ 0 - 134
src/locale/en-US.js

@@ -1,134 +0,0 @@
-import appLocaleData from 'react-intl/locale-data/en';
-import antdEn from 'antd/lib/locale-provider/en_US';
-// import enMessages from '../../locales/en.json';
-
-export default {
-  locale: 'en-US',
-  data: appLocaleData,
-  antd: antdEn,
-  messages: {
-    'navbar.lang': 'English',
-    'menu.home': 'Home',
-    'menu.dashboard': 'Dashboard',
-    'menu.dashboard.analysis': 'Analysis',
-    'menu.dashboard.monitor': 'Monitor',
-    'menu.dashboard.workplace': 'Workplace',
-    'menu.form': 'Form',
-    'menu.form.basicform': 'Basic Form',
-    'menu.form.stepform': 'Step Form',
-    'menu.form.advancedform': 'Advanced Form',
-    'menu.list': 'List',
-    'menu.list.searchlist': 'Search List',
-    'menu.list.basiclist': 'Basic List',
-    'menu.list.cardlist': 'Card List',
-    'menu.list.searchlist.articles': 'Search List(articles)',
-    'menu.list.searchlist.projects': 'Search List(projects)',
-    'menu.list.searchlist.applications': 'Search List(applications)',
-    'menu.profile': 'Profile',
-    'menu.profile.basic': 'Basic',
-    'menu.profile.advanced': 'Advanced',
-    'menu.result': 'Result',
-    'menu.result.success': 'Success',
-    'menu.result.fail': 'Fail',
-    'menu.exception': 'Exception',
-    'menu.exception.not-permission': '403',
-    'menu.exception.not-find': '404',
-    'menu.exception.server-error': '500',
-    'menu.exception.trigger': 'Trigger',
-    'menu.account': 'Account',
-    'menu.account.center': 'Account Center',
-    'menu.account.settings': 'Account Settings',
-    'menu.account.trigger': 'Trigger Error',
-    'app.home.introduce': 'introduce',
-    'app.analysis.test': 'Gongzhuan road No.{no} shop',
-    'app.analysis.introduce': 'Introduce',
-    'app.analysis.total-sales': 'total sales',
-    'app.analysis.day-sales': 'Day Sales',
-    'app.analysis.visits': 'Visits',
-    'app.analysis.visits-trend': 'Visits Trend',
-    'app.analysis.visits-ranking': 'Visits Ranking',
-    'app.analysis.day-visits': 'Day Visits',
-    'app.analysis.week': 'week ratio',
-    'app.analysis.day': 'day ratio',
-    'app.analysis.payments': 'Payments',
-    'app.analysis.conversion-rate': 'Conversion Rate',
-    'app.analysis.operational-effect': 'Operational Effect',
-    'app.analysis.sales-trend': 'Stores Sales Trend',
-    'app.analysis.sales-ranking': 'sales ranking',
-    'app.analysis.all-year': 'All Year',
-    'app.analysis.all-month': 'All Month',
-    'app.analysis.all-week': 'All Week',
-    'app.analysis.all-day': 'All day',
-    'app.analysis.search-users': 'Search Users',
-    'app.analysis.per-capita-search': 'Per Capita Search',
-    'app.analysis.online-top-search': 'Online Top Search',
-    'app.analysis.the-proportion-of-sales': 'The Proportion Of Sales',
-    'app.analysis.channel.all': 'ALL',
-    'app.analysis.channel.online': 'Online',
-    'app.analysis.channel.stores': 'Stores',
-    'app.analysis.sales': 'Sales',
-    'app.analysis.traffic': 'Traffic',
-    'app.analysis.table.rank': 'Rank',
-    'app.analysis.table.search-keyword': 'Keyword',
-    'app.analysis.table.users': 'Users',
-    'app.analysis.table.weekly-range': 'Weekly Range',
-    'app.settings.menuMap.basic': 'Basic Settings',
-    'app.settings.menuMap.security': 'Security Settings',
-    'app.settings.menuMap.binding': 'Account Binding',
-    'app.settings.menuMap.notification': 'New Message Notification',
-    'app.settings.basic.avatar': 'Change avatar',
-    'app.settings.basic.email': 'Email',
-    'app.settings.basic.email-message': 'Please input your email!',
-    'app.settings.basic.nickname': 'Nickname',
-    'app.settings.basic.nickname-message': 'Please input your Nickname!',
-    'app.settings.basic.profile': 'Personal profile',
-    'app.settings.basic.profile-message': 'Please input your personal profile!',
-    'app.settings.basic.profile-placeholder': 'Brief introduction to yourself',
-    'app.settings.basic.country': 'Country/Region',
-    'app.settings.basic.country-message': 'Please input your country!',
-    'app.settings.basic.geographic': 'Province or city',
-    'app.settings.basic.geographic-message': 'Please input your geographic info!',
-    'app.settings.basic.address': 'Street Address',
-    'app.settings.basic.address-message': 'Please input your address!',
-    'app.settings.basic.phone': 'Phone Number',
-    'app.settings.basic.phone-message': 'Please input your phone!',
-    'app.settings.basic.update': 'Update Information',
-    'app.settings.security.strong': 'Strong',
-    'app.settings.security.medium': 'Medium',
-    'app.settings.security.weak': 'Weak',
-    'app.settings.security.password': 'Account Password',
-    'app.settings.security.password-description': 'Current password strength:',
-    'app.settings.security.phone': 'Security Phone',
-    'app.settings.security.phone-description': 'Bound phone:',
-    'app.settings.security.question': 'Security Question',
-    'app.settings.security.question-description':
-      'The security question is not set, and the security policy can effectively protect the account security',
-    'app.settings.security.email': 'Backup Email',
-    'app.settings.security.email-description': 'Bound Email:',
-    'app.settings.security.mfa': 'MFA Device',
-    'app.settings.security.mfa-description':
-      'Unbound MFA device, after binding, can be confirmed twice',
-    'app.settings.security.modify': 'Modify',
-    'app.settings.security.set': 'Set',
-    'app.settings.security.bind': 'Bind',
-    'app.settings.binding.taobao': 'Binding Taobao',
-    'app.settings.binding.taobao-description': 'Currently unbound Taobao account',
-    'app.settings.binding.alipay': 'Binding Alipay',
-    'app.settings.binding.alipay-description': 'Currently unbound Alipay account',
-    'app.settings.binding.dingding': 'Binding DingTalk',
-    'app.settings.binding.dingding-description': 'Currently unbound DingTalk account',
-    'app.settings.binding.bind': 'Bind',
-    'app.settings.notification.password': 'Account Password',
-    'app.settings.notification.password-description':
-      'Messages from other users will be notified in the form of a station letter',
-    'app.settings.notification.messages': 'System Messages',
-    'app.settings.notification.messages-description':
-      'System messages will be notified in the form of a station letter',
-    'app.settings.notification.todo': 'To-do Notification',
-    'app.settings.notification.todo-description':
-      'The to-do list will be notified in the form of a letter from the station',
-    'app.settings.open': 'Open',
-    'app.settings.close': 'Close',
-    // ...enMessages,
-  },
-};

+ 0 - 129
src/locale/zh-CN.js

@@ -1,129 +0,0 @@
-import appLocaleData from 'react-intl/locale-data/zh';
-import antdZh from 'antd/lib/locale-provider/zh_CN';
-// import zhMessages from '../../locales/zh.json';
-
-export default {
-  locale: 'zh-CN',
-  data: appLocaleData,
-  antd: antdZh,
-  messages: {
-    'navbar.lang': '中文',
-    'menu.home': '首页',
-    'menu.dashboard': 'Dashboard',
-    'menu.dashboard.analysis': '分析页',
-    'menu.dashboard.monitor': '监控页',
-    'menu.dashboard.workplace': '工作台',
-    'menu.form': '表单页',
-    'menu.form.basicform': '基础表单',
-    'menu.form.stepform': '分布表单',
-    'menu.form.advancedform': '高级表单',
-    'menu.list': '列表页',
-    'menu.list.searchlist': '搜索列表',
-    'menu.list.basiclist': '标准列表',
-    'menu.list.cardlist': '卡片列表',
-    'menu.list.searchlist.articles': '搜索列表(文章)',
-    'menu.list.searchlist.projects': '搜索列表(项目)',
-    'menu.list.searchlist.applications': '搜索列表(应用)',
-    'menu.profile': '详情页',
-    'menu.profile.basic': '详情页',
-    'menu.profile.advanced': '详情页',
-    'menu.result': '结果页',
-    'menu.result.success': '成功页',
-    'menu.result.fail': '失败页',
-    'menu.exception': '异常页',
-    'menu.exception.not-permission': '403',
-    'menu.exception.not-find': '404',
-    'menu.exception.server-error': '500',
-    'menu.exception.trigger': '触发错误',
-    'menu.account': '个人页',
-    'menu.account.center': '个人中心',
-    'menu.account.settings': '个人设置',
-    'menu.account.trigger': '触发报错',
-    'app.home.introduce': '介绍',
-    'app.analysis.test': '工专路 {no} 号店',
-    'app.analysis.introduce': '指标说明',
-    'app.analysis.total-sales': '总销售额',
-    'app.analysis.day-sales': '日销售额',
-    'app.analysis.visits': '访问量',
-    'app.analysis.visits-trend': '访问量趋势',
-    'app.analysis.visits-ranking': '门店访问量排名',
-    'app.analysis.day-visits': '日访问量',
-    'app.analysis.week': '周同比',
-    'app.analysis.day': '日同比',
-    'app.analysis.payments': '支付笔数',
-    'app.analysis.conversion-rate': '转化率',
-    'app.analysis.operational-effect': '运营活动效果',
-    'app.analysis.sales-trend': '销售趋势',
-    'app.analysis.sales-ranking': '门店销售额排名',
-    'app.analysis.all-year': '全年',
-    'app.analysis.all-month': '本月',
-    'app.analysis.all-week': '本周',
-    'app.analysis.all-day': '今日',
-    'app.analysis.search-users': '搜索用户数',
-    'app.analysis.per-capita-search': '人均搜索次数',
-    'app.analysis.online-top-search': '线上热门搜索',
-    'app.analysis.the-proportion-of-sales': '销售额类别占比',
-    'app.analysis.channel.all': '全部渠道',
-    'app.analysis.channel.online': '线上',
-    'app.analysis.channel.stores': '门店',
-    'app.analysis.sales': '销售额',
-    'app.analysis.traffic': '客流量',
-    'app.analysis.table.rank': '排名',
-    'app.analysis.table.search-keyword': '搜索关键词',
-    'app.analysis.table.users': '用户数',
-    'app.analysis.table.weekly-range': '周涨幅',
-    'app.settings.menuMap.basic': '基本设置',
-    'app.settings.menuMap.security': '安全设置',
-    'app.settings.menuMap.binding': '账号绑定',
-    'app.settings.menuMap.notification': '新消息通知',
-    'app.settings.basic.avatar': '更换头像',
-    'app.settings.basic.email': '邮箱',
-    'app.settings.basic.email-message': '请输入您的邮箱!',
-    'app.settings.basic.nickname': '昵称',
-    'app.settings.basic.nickname-message': '请输入您的昵称!',
-    'app.settings.basic.profile': '个人简介',
-    'app.settings.basic.profile-message': '请输入个人简介!',
-    'app.settings.basic.profile-placeholder': '个人简介',
-    'app.settings.basic.country': '国家/地区',
-    'app.settings.basic.country-message': '请输入您的国家或地区!',
-    'app.settings.basic.geographic': '所在省市',
-    'app.settings.basic.geographic-message': '请输入您的所在省市!',
-    'app.settings.basic.address': '街道地址',
-    'app.settings.basic.address-message': '请输入您的街道地址!',
-    'app.settings.basic.phone': '联系电话',
-    'app.settings.basic.phone-message': '请输入您的联系电话!',
-    'app.settings.security.strong': '强',
-    'app.settings.security.medium': '中',
-    'app.settings.security.weak': '弱',
-    'app.settings.security.password': '账户密码',
-    'app.settings.security.password-description': '当前密码强度:',
-    'app.settings.security.phone': '密保手机',
-    'app.settings.security.phone-description': '已绑定手机:',
-    'app.settings.security.question': '密保问题',
-    'app.settings.security.question-description': '未设置密保问题,密保问题可有效保护账户安全',
-    'app.settings.security.email': '备用邮箱',
-    'app.settings.security.email-description': '已绑定邮箱:',
-    'app.settings.security.mfa': 'MFA 设备',
-    'app.settings.security.mfa-description': '未绑定 MFA 设备,绑定后,可以进行二次确认',
-    'app.settings.security.modify': '修改',
-    'app.settings.security.set': '设置',
-    'app.settings.security.bind': '绑定',
-    'app.settings.binding.taobao': '绑定淘宝',
-    'app.settings.binding.taobao-description': '当前未绑定淘宝账号',
-    'app.settings.binding.alipay': '绑定支付宝',
-    'app.settings.binding.alipay-description': '当前未绑定支付宝账号',
-    'app.settings.binding.dingding': '绑定钉钉',
-    'app.settings.binding.dingding-description': '当前未绑定钉钉账号',
-    'app.settings.binding.bind': '绑定',
-    'app.settings.notification.password': '账户密码',
-    'app.settings.notification.password-description': '其他用户的消息将以站内信的形式通知',
-    'app.settings.notification.messages': '系统消息',
-    'app.settings.notification.messages-description': '系统消息将以站内信的形式通知',
-    'app.settings.notification.todo': '账户密码',
-    'app.settings.notification.todo-description': '账户密码',
-    'app.settings.open': '开',
-    'app.settings.close': '关',
-
-    // ...zhMessages,
-  },
-};

+ 124 - 0
src/locales/en-US.js

@@ -0,0 +1,124 @@
+export default {
+  'navbar.lang': 'English',
+  'menu.home': 'Home',
+  'menu.dashboard': 'Dashboard',
+  'menu.dashboard.analysis': 'Analysis',
+  'menu.dashboard.monitor': 'Monitor',
+  'menu.dashboard.workplace': 'Workplace',
+  'menu.form': 'Form',
+  'menu.form.basicform': 'Basic Form',
+  'menu.form.stepform': 'Step Form',
+  'menu.form.advancedform': 'Advanced Form',
+  'menu.list': 'List',
+  'menu.list.searchlist': 'Search List',
+  'menu.list.basiclist': 'Basic List',
+  'menu.list.cardlist': 'Card List',
+  'menu.list.searchlist.articles': 'Search List(articles)',
+  'menu.list.searchlist.projects': 'Search List(projects)',
+  'menu.list.searchlist.applications': 'Search List(applications)',
+  'menu.profile': 'Profile',
+  'menu.profile.basic': 'Basic',
+  'menu.profile.advanced': 'Advanced',
+  'menu.result': 'Result',
+  'menu.result.success': 'Success',
+  'menu.result.fail': 'Fail',
+  'menu.exception': 'Exception',
+  'menu.exception.not-permission': '403',
+  'menu.exception.not-find': '404',
+  'menu.exception.server-error': '500',
+  'menu.exception.trigger': 'Trigger',
+  'menu.account': 'Account',
+  'menu.account.center': 'Account Center',
+  'menu.account.settings': 'Account Settings',
+  'menu.account.trigger': 'Trigger Error',
+  'app.home.introduce': 'introduce',
+  'app.analysis.test': 'Gongzhuan road No.{no} shop',
+  'app.analysis.introduce': 'Introduce',
+  'app.analysis.total-sales': 'total sales',
+  'app.analysis.day-sales': 'Day Sales',
+  'app.analysis.visits': 'Visits',
+  'app.analysis.visits-trend': 'Visits Trend',
+  'app.analysis.visits-ranking': 'Visits Ranking',
+  'app.analysis.day-visits': 'Day Visits',
+  'app.analysis.week': 'week ratio',
+  'app.analysis.day': 'day ratio',
+  'app.analysis.payments': 'Payments',
+  'app.analysis.conversion-rate': 'Conversion Rate',
+  'app.analysis.operational-effect': 'Operational Effect',
+  'app.analysis.sales-trend': 'Stores Sales Trend',
+  'app.analysis.sales-ranking': 'sales ranking',
+  'app.analysis.all-year': 'All Year',
+  'app.analysis.all-month': 'All Month',
+  'app.analysis.all-week': 'All Week',
+  'app.analysis.all-day': 'All day',
+  'app.analysis.search-users': 'Search Users',
+  'app.analysis.per-capita-search': 'Per Capita Search',
+  'app.analysis.online-top-search': 'Online Top Search',
+  'app.analysis.the-proportion-of-sales': 'The Proportion Of Sales',
+  'app.analysis.channel.all': 'ALL',
+  'app.analysis.channel.online': 'Online',
+  'app.analysis.channel.stores': 'Stores',
+  'app.analysis.sales': 'Sales',
+  'app.analysis.traffic': 'Traffic',
+  'app.analysis.table.rank': 'Rank',
+  'app.analysis.table.search-keyword': 'Keyword',
+  'app.analysis.table.users': 'Users',
+  'app.analysis.table.weekly-range': 'Weekly Range',
+  'app.settings.menuMap.basic': 'Basic Settings',
+  'app.settings.menuMap.security': 'Security Settings',
+  'app.settings.menuMap.binding': 'Account Binding',
+  'app.settings.menuMap.notification': 'New Message Notification',
+  'app.settings.basic.avatar': 'Change avatar',
+  'app.settings.basic.email': 'Email',
+  'app.settings.basic.email-message': 'Please input your email!',
+  'app.settings.basic.nickname': 'Nickname',
+  'app.settings.basic.nickname-message': 'Please input your Nickname!',
+  'app.settings.basic.profile': 'Personal profile',
+  'app.settings.basic.profile-message': 'Please input your personal profile!',
+  'app.settings.basic.profile-placeholder': 'Brief introduction to yourself',
+  'app.settings.basic.country': 'Country/Region',
+  'app.settings.basic.country-message': 'Please input your country!',
+  'app.settings.basic.geographic': 'Province or city',
+  'app.settings.basic.geographic-message': 'Please input your geographic info!',
+  'app.settings.basic.address': 'Street Address',
+  'app.settings.basic.address-message': 'Please input your address!',
+  'app.settings.basic.phone': 'Phone Number',
+  'app.settings.basic.phone-message': 'Please input your phone!',
+  'app.settings.basic.update': 'Update Information',
+  'app.settings.security.strong': 'Strong',
+  'app.settings.security.medium': 'Medium',
+  'app.settings.security.weak': 'Weak',
+  'app.settings.security.password': 'Account Password',
+  'app.settings.security.password-description': 'Current password strength:',
+  'app.settings.security.phone': 'Security Phone',
+  'app.settings.security.phone-description': 'Bound phone:',
+  'app.settings.security.question': 'Security Question',
+  'app.settings.security.question-description':
+    'The security question is not set, and the security policy can effectively protect the account security',
+  'app.settings.security.email': 'Backup Email',
+  'app.settings.security.email-description': 'Bound Email:',
+  'app.settings.security.mfa': 'MFA Device',
+  'app.settings.security.mfa-description':
+    'Unbound MFA device, after binding, can be confirmed twice',
+  'app.settings.security.modify': 'Modify',
+  'app.settings.security.set': 'Set',
+  'app.settings.security.bind': 'Bind',
+  'app.settings.binding.taobao': 'Binding Taobao',
+  'app.settings.binding.taobao-description': 'Currently unbound Taobao account',
+  'app.settings.binding.alipay': 'Binding Alipay',
+  'app.settings.binding.alipay-description': 'Currently unbound Alipay account',
+  'app.settings.binding.dingding': 'Binding DingTalk',
+  'app.settings.binding.dingding-description': 'Currently unbound DingTalk account',
+  'app.settings.binding.bind': 'Bind',
+  'app.settings.notification.password': 'Account Password',
+  'app.settings.notification.password-description':
+    'Messages from other users will be notified in the form of a station letter',
+  'app.settings.notification.messages': 'System Messages',
+  'app.settings.notification.messages-description':
+    'System messages will be notified in the form of a station letter',
+  'app.settings.notification.todo': 'To-do Notification',
+  'app.settings.notification.todo-description':
+    'The to-do list will be notified in the form of a letter from the station',
+  'app.settings.open': 'Open',
+  'app.settings.close': 'Close',
+};

+ 1 - 1
src/locale/localeContext.js

@@ -1,5 +1,5 @@
 import React from 'react';
-import { addLocaleData, IntlProvider } from 'react-intl';
+import { addLocaleData, IntlProvider } from 'umi/locale';
 import { LocaleProvider } from 'antd';
 import enLocale from './en-US';
 import cnLocale from './zh-CN';

+ 120 - 0
src/locales/zh-CN.js

@@ -0,0 +1,120 @@
+// import zhMessages from '../../locales/zh.json';
+
+export default {
+  'navbar.lang': '中文',
+  'menu.home': '首页',
+  'menu.dashboard': 'Dashboard',
+  'menu.dashboard.analysis': '分析页',
+  'menu.dashboard.monitor': '监控页',
+  'menu.dashboard.workplace': '工作台',
+  'menu.form': '表单页',
+  'menu.form.basicform': '基础表单',
+  'menu.form.stepform': '分布表单',
+  'menu.form.advancedform': '高级表单',
+  'menu.list': '列表页',
+  'menu.list.searchlist': '搜索列表',
+  'menu.list.basiclist': '标准列表',
+  'menu.list.cardlist': '卡片列表',
+  'menu.list.searchlist.articles': '搜索列表(文章)',
+  'menu.list.searchlist.projects': '搜索列表(项目)',
+  'menu.list.searchlist.applications': '搜索列表(应用)',
+  'menu.profile': '详情页',
+  'menu.profile.basic': '详情页',
+  'menu.profile.advanced': '详情页',
+  'menu.result': '结果页',
+  'menu.result.success': '成功页',
+  'menu.result.fail': '失败页',
+  'menu.exception': '异常页',
+  'menu.exception.not-permission': '403',
+  'menu.exception.not-find': '404',
+  'menu.exception.server-error': '500',
+  'menu.exception.trigger': '触发错误',
+  'menu.account': '个人页',
+  'menu.account.center': '个人中心',
+  'menu.account.settings': '个人设置',
+  'menu.account.trigger': '触发报错',
+  'app.home.introduce': '介绍',
+  'app.analysis.test': '工专路 {no} 号店',
+  'app.analysis.introduce': '指标说明',
+  'app.analysis.total-sales': '总销售额',
+  'app.analysis.day-sales': '日销售额',
+  'app.analysis.visits': '访问量',
+  'app.analysis.visits-trend': '访问量趋势',
+  'app.analysis.visits-ranking': '门店访问量排名',
+  'app.analysis.day-visits': '日访问量',
+  'app.analysis.week': '周同比',
+  'app.analysis.day': '日同比',
+  'app.analysis.payments': '支付笔数',
+  'app.analysis.conversion-rate': '转化率',
+  'app.analysis.operational-effect': '运营活动效果',
+  'app.analysis.sales-trend': '销售趋势',
+  'app.analysis.sales-ranking': '门店销售额排名',
+  'app.analysis.all-year': '全年',
+  'app.analysis.all-month': '本月',
+  'app.analysis.all-week': '本周',
+  'app.analysis.all-day': '今日',
+  'app.analysis.search-users': '搜索用户数',
+  'app.analysis.per-capita-search': '人均搜索次数',
+  'app.analysis.online-top-search': '线上热门搜索',
+  'app.analysis.the-proportion-of-sales': '销售额类别占比',
+  'app.analysis.channel.all': '全部渠道',
+  'app.analysis.channel.online': '线上',
+  'app.analysis.channel.stores': '门店',
+  'app.analysis.sales': '销售额',
+  'app.analysis.traffic': '客流量',
+  'app.analysis.table.rank': '排名',
+  'app.analysis.table.search-keyword': '搜索关键词',
+  'app.analysis.table.users': '用户数',
+  'app.analysis.table.weekly-range': '周涨幅',
+  'app.settings.menuMap.basic': '基本设置',
+  'app.settings.menuMap.security': '安全设置',
+  'app.settings.menuMap.binding': '账号绑定',
+  'app.settings.menuMap.notification': '新消息通知',
+  'app.settings.basic.avatar': '更换头像',
+  'app.settings.basic.email': '邮箱',
+  'app.settings.basic.email-message': '请输入您的邮箱!',
+  'app.settings.basic.nickname': '昵称',
+  'app.settings.basic.nickname-message': '请输入您的昵称!',
+  'app.settings.basic.profile': '个人简介',
+  'app.settings.basic.profile-message': '请输入个人简介!',
+  'app.settings.basic.profile-placeholder': '个人简介',
+  'app.settings.basic.country': '国家/地区',
+  'app.settings.basic.country-message': '请输入您的国家或地区!',
+  'app.settings.basic.geographic': '所在省市',
+  'app.settings.basic.geographic-message': '请输入您的所在省市!',
+  'app.settings.basic.address': '街道地址',
+  'app.settings.basic.address-message': '请输入您的街道地址!',
+  'app.settings.basic.phone': '联系电话',
+  'app.settings.basic.phone-message': '请输入您的联系电话!',
+  'app.settings.security.strong': '强',
+  'app.settings.security.medium': '中',
+  'app.settings.security.weak': '弱',
+  'app.settings.security.password': '账户密码',
+  'app.settings.security.password-description': '当前密码强度:',
+  'app.settings.security.phone': '密保手机',
+  'app.settings.security.phone-description': '已绑定手机:',
+  'app.settings.security.question': '密保问题',
+  'app.settings.security.question-description': '未设置密保问题,密保问题可有效保护账户安全',
+  'app.settings.security.email': '备用邮箱',
+  'app.settings.security.email-description': '已绑定邮箱:',
+  'app.settings.security.mfa': 'MFA 设备',
+  'app.settings.security.mfa-description': '未绑定 MFA 设备,绑定后,可以进行二次确认',
+  'app.settings.security.modify': '修改',
+  'app.settings.security.set': '设置',
+  'app.settings.security.bind': '绑定',
+  'app.settings.binding.taobao': '绑定淘宝',
+  'app.settings.binding.taobao-description': '当前未绑定淘宝账号',
+  'app.settings.binding.alipay': '绑定支付宝',
+  'app.settings.binding.alipay-description': '当前未绑定支付宝账号',
+  'app.settings.binding.dingding': '绑定钉钉',
+  'app.settings.binding.dingding-description': '当前未绑定钉钉账号',
+  'app.settings.binding.bind': '绑定',
+  'app.settings.notification.password': '账户密码',
+  'app.settings.notification.password-description': '其他用户的消息将以站内信的形式通知',
+  'app.settings.notification.messages': '系统消息',
+  'app.settings.notification.messages-description': '系统消息将以站内信的形式通知',
+  'app.settings.notification.todo': '账户密码',
+  'app.settings.notification.todo-description': '账户密码',
+  'app.settings.open': '开',
+  'app.settings.close': '关',
+};

+ 17 - 24
src/pages/Account/Settings/BaseView.js

@@ -1,5 +1,5 @@
 import React, { Component, Fragment } from 'react';
-import { injectIntl, FormattedMessage } from 'react-intl';
+import { formatMessage, FormattedMessage } from 'umi/locale';
 import { Form, Input, Upload, Select, Button } from 'antd';
 import { connect } from 'dva';
 import styles from './BaseView.less';
@@ -83,56 +83,52 @@ class BaseView extends Component {
   render() {
     const {
       form: { getFieldDecorator },
-      intl,
     } = this.props;
     return (
       <div className={styles.baseView} ref={this.getViewDom}>
         <div className={styles.left}>
           <Form layout="vertical" onSubmit={this.handleSubmit} hideRequiredMark>
-            <FormItem label={intl.formatMessage({ id: 'app.settings.basic.email' }, {})}>
+            <FormItem label={formatMessage({ id: 'app.settings.basic.email' }, {})}>
               {getFieldDecorator('email', {
                 rules: [
                   {
                     required: true,
-                    message: intl.formatMessage({ id: 'app.settings.basic.email-message' }, {}),
+                    message: formatMessage({ id: 'app.settings.basic.email-message' }, {}),
                   },
                 ],
               })(<Input />)}
             </FormItem>
-            <FormItem label={intl.formatMessage({ id: 'app.settings.basic.nickname' }, {})}>
+            <FormItem label={formatMessage({ id: 'app.settings.basic.nickname' }, {})}>
               {getFieldDecorator('name', {
                 rules: [
                   {
                     required: true,
-                    message: intl.formatMessage({ id: 'app.settings.basic.nickname-message' }, {}),
+                    message: formatMessage({ id: 'app.settings.basic.nickname-message' }, {}),
                   },
                 ],
               })(<Input />)}
             </FormItem>
-            <FormItem label={intl.formatMessage({ id: 'app.settings.basic.profile' }, {})}>
+            <FormItem label={formatMessage({ id: 'app.settings.basic.profile' }, {})}>
               {getFieldDecorator('profile', {
                 rules: [
                   {
                     required: true,
-                    message: intl.formatMessage({ id: 'app.settings.basic.profile-message' }, {}),
+                    message: formatMessage({ id: 'app.settings.basic.profile-message' }, {}),
                   },
                 ],
               })(
                 <Input.TextArea
-                  placeholder={intl.formatMessage(
-                    { id: 'app.settings.basic.profile-placeholder' },
-                    {}
-                  )}
+                  placeholder={formatMessage({ id: 'app.settings.basic.profile-placeholder' }, {})}
                   rows={4}
                 />
               )}
             </FormItem>
-            <FormItem label={intl.formatMessage({ id: 'app.settings.basic.country' }, {})}>
+            <FormItem label={formatMessage({ id: 'app.settings.basic.country' }, {})}>
               {getFieldDecorator('country', {
                 rules: [
                   {
                     required: true,
-                    message: intl.formatMessage({ id: 'app.settings.basic.country-message' }, {}),
+                    message: formatMessage({ id: 'app.settings.basic.country-message' }, {}),
                   },
                 ],
               })(
@@ -141,15 +137,12 @@ class BaseView extends Component {
                 </Select>
               )}
             </FormItem>
-            <FormItem label={intl.formatMessage({ id: 'app.settings.basic.geographic' }, {})}>
+            <FormItem label={formatMessage({ id: 'app.settings.basic.geographic' }, {})}>
               {getFieldDecorator('geographic', {
                 rules: [
                   {
                     required: true,
-                    message: intl.formatMessage(
-                      { id: 'app.settings.basic.geographic-message' },
-                      {}
-                    ),
+                    message: formatMessage({ id: 'app.settings.basic.geographic-message' }, {}),
                   },
                   {
                     validator: validatorGeographic,
@@ -157,22 +150,22 @@ class BaseView extends Component {
                 ],
               })(<GeographicView />)}
             </FormItem>
-            <FormItem label={intl.formatMessage({ id: 'app.settings.basic.address' }, {})}>
+            <FormItem label={formatMessage({ id: 'app.settings.basic.address' }, {})}>
               {getFieldDecorator('address', {
                 rules: [
                   {
                     required: true,
-                    message: intl.formatMessage({ id: 'app.settings.basic.address-message' }, {}),
+                    message: formatMessage({ id: 'app.settings.basic.address-message' }, {}),
                   },
                 ],
               })(<Input />)}
             </FormItem>
-            <FormItem label={intl.formatMessage({ id: 'app.settings.basic.phone' }, {})}>
+            <FormItem label={formatMessage({ id: 'app.settings.basic.phone' }, {})}>
               {getFieldDecorator('phone', {
                 rules: [
                   {
                     required: true,
-                    message: intl.formatMessage({ id: 'app.settings.basic.phone-message' }, {}),
+                    message: formatMessage({ id: 'app.settings.basic.phone-message' }, {}),
                   },
                   { validator: validatorPhone },
                 ],
@@ -193,4 +186,4 @@ class BaseView extends Component {
     );
   }
 }
-export default injectIntl(BaseView);
+export default BaseView;

+ 8 - 9
src/pages/Account/Settings/BindingView.js

@@ -1,14 +1,13 @@
 import React, { Component, Fragment } from 'react';
-import { injectIntl, FormattedMessage } from 'react-intl';
+import { formatMessage, FormattedMessage } from 'umi/locale';
 import { Icon, List } from 'antd';
 
 class BindingView extends Component {
   getData = () => {
-    const { intl } = this.props;
     return [
       {
-        title: intl.formatMessage({ id: 'app.settings.binding.taobao' }, {}),
-        description: intl.formatMessage({ id: 'app.settings.binding.taobao-description' }, {}),
+        title: formatMessage({ id: 'app.settings.binding.taobao' }, {}),
+        description: formatMessage({ id: 'app.settings.binding.taobao-description' }, {}),
         actions: [
           <a>
             <FormattedMessage id="app.settings.binding.bind" defaultMessage="Bind" />
@@ -17,8 +16,8 @@ class BindingView extends Component {
         avatar: <Icon type="taobao" className="taobao" />,
       },
       {
-        title: intl.formatMessage({ id: 'app.settings.binding.alipay' }, {}),
-        description: intl.formatMessage({ id: 'app.settings.binding.alipay-description' }, {}),
+        title: formatMessage({ id: 'app.settings.binding.alipay' }, {}),
+        description: formatMessage({ id: 'app.settings.binding.alipay-description' }, {}),
         actions: [
           <a>
             <FormattedMessage id="app.settings.binding.bind" defaultMessage="Bind" />
@@ -27,8 +26,8 @@ class BindingView extends Component {
         avatar: <Icon type="alipay" className="alipay" />,
       },
       {
-        title: intl.formatMessage({ id: 'app.settings.binding.dingding' }, {}),
-        description: intl.formatMessage({ id: 'app.settings.binding.dingding-description' }, {}),
+        title: formatMessage({ id: 'app.settings.binding.dingding' }, {}),
+        description: formatMessage({ id: 'app.settings.binding.dingding-description' }, {}),
         actions: [
           <a>
             <FormattedMessage id="app.settings.binding.bind" defaultMessage="Bind" />
@@ -59,4 +58,4 @@ class BindingView extends Component {
     );
   }
 }
-export default injectIntl(BindingView);
+export default BindingView;

+ 1 - 1
src/pages/Account/Settings/Info.js

@@ -1,7 +1,7 @@
 import React, { Component } from 'react';
 import { connect } from 'dva';
 import { routerRedux } from 'dva/router';
-import { FormattedMessage } from 'react-intl';
+import { FormattedMessage } from 'umi/locale';
 import { Menu } from 'antd';
 import styles from './Info.less';
 import GridContent from '../../layouts/GridContent';

+ 10 - 17
src/pages/Account/Settings/NotificationView.js

@@ -1,37 +1,30 @@
 import React, { Component, Fragment } from 'react';
-import { injectIntl } from 'react-intl';
+import { formatMessage } from 'umi/locale';
 import { Switch, List } from 'antd';
 
 class NotificationView extends Component {
   getData = () => {
-    const { intl } = this.props;
     const Action = (
       <Switch
-        checkedChildren={intl.formatMessage({ id: 'app.settings.open' }, {})}
-        unCheckedChildren={intl.formatMessage({ id: 'app.settings.close' }, {})}
+        checkedChildren={formatMessage({ id: 'app.settings.open' }, {})}
+        unCheckedChildren={formatMessage({ id: 'app.settings.close' }, {})}
         defaultChecked
       />
     );
     return [
       {
-        title: intl.formatMessage({ id: 'app.settings.notification.password' }, {}),
-        description: intl.formatMessage(
-          { id: 'app.settings.notification.password-description' },
-          {}
-        ),
+        title: formatMessage({ id: 'app.settings.notification.password' }, {}),
+        description: formatMessage({ id: 'app.settings.notification.password-description' }, {}),
         actions: [Action],
       },
       {
-        title: intl.formatMessage({ id: 'app.settings.notification.messages' }, {}),
-        description: intl.formatMessage(
-          { id: 'app.settings.notification.messages-description' },
-          {}
-        ),
+        title: formatMessage({ id: 'app.settings.notification.messages' }, {}),
+        description: formatMessage({ id: 'app.settings.notification.messages-description' }, {}),
         actions: [Action],
       },
       {
-        title: intl.formatMessage({ id: 'app.settings.notification.todo' }, {}),
-        description: intl.formatMessage({ id: 'app.settings.notification.todo-description' }, {}),
+        title: formatMessage({ id: 'app.settings.notification.todo' }, {}),
+        description: formatMessage({ id: 'app.settings.notification.todo-description' }, {}),
         actions: [Action],
       },
     ];
@@ -53,4 +46,4 @@ class NotificationView extends Component {
     );
   }
 }
-export default injectIntl(NotificationView);
+export default NotificationView;

+ 12 - 14
src/pages/Account/Settings/SecurityView.js

@@ -1,5 +1,5 @@
 import React, { Component, Fragment } from 'react';
-import { injectIntl, FormattedMessage } from 'react-intl';
+import { formatMessage, FormattedMessage } from 'umi/locale';
 import { List } from 'antd';
 // import { getTimeDistance } from '../../../utils/utils';
 
@@ -23,14 +23,12 @@ const passwordStrength = {
 
 class SecurityView extends Component {
   getData = () => {
-    const { intl } = this.props;
     return [
       {
-        title: intl.formatMessage({ id: 'app.settings.security.password' }, {}),
+        title: formatMessage({ id: 'app.settings.security.password' }, {}),
         description: (
           <Fragment>
-            {' '}
-            {intl.formatMessage({ id: 'app.settings.security.password-description' }, {})}:{
+            {formatMessage({ id: 'app.settings.security.password-description' }, {})}:{
               passwordStrength.strong
             }
           </Fragment>
@@ -42,8 +40,8 @@ class SecurityView extends Component {
         ],
       },
       {
-        title: intl.formatMessage({ id: 'app.settings.security.phone' }, {}),
-        description: `${intl.formatMessage(
+        title: formatMessage({ id: 'app.settings.security.phone' }, {}),
+        description: `${formatMessage(
           { id: 'app.settings.security.phone-description' },
           {}
         )}:138****8293`,
@@ -54,8 +52,8 @@ class SecurityView extends Component {
         ],
       },
       {
-        title: intl.formatMessage({ id: 'app.settings.security.question' }, {}),
-        description: intl.formatMessage({ id: 'app.settings.security.question-description' }, {}),
+        title: formatMessage({ id: 'app.settings.security.question' }, {}),
+        description: formatMessage({ id: 'app.settings.security.question-description' }, {}),
         actions: [
           <a>
             <FormattedMessage id="app.settings.security.set" defaultMessage="Set" />
@@ -63,8 +61,8 @@ class SecurityView extends Component {
         ],
       },
       {
-        title: intl.formatMessage({ id: 'app.settings.security.email' }, {}),
-        description: `${intl.formatMessage(
+        title: formatMessage({ id: 'app.settings.security.email' }, {}),
+        description: `${formatMessage(
           { id: 'app.settings.security.email-description' },
           {}
         )}:ant***sign.com`,
@@ -75,8 +73,8 @@ class SecurityView extends Component {
         ],
       },
       {
-        title: intl.formatMessage({ id: 'app.settings.security.mfa' }, {}),
-        description: intl.formatMessage({ id: 'app.settings.security.mfa-description' }, {}),
+        title: formatMessage({ id: 'app.settings.security.mfa' }, {}),
+        description: formatMessage({ id: 'app.settings.security.mfa-description' }, {}),
         actions: [
           <a>
             <FormattedMessage id="app.settings.security.bind" defaultMessage="Bind" />
@@ -102,4 +100,4 @@ class SecurityView extends Component {
     );
   }
 }
-export default injectIntl(SecurityView);
+export default SecurityView;

+ 3 - 4
src/pages/Dashboard/Analysis.js

@@ -1,6 +1,6 @@
 import React, { Component } from 'react';
 import { connect } from 'dva';
-import { injectIntl, FormattedMessage } from 'react-intl';
+import { formatMessage, FormattedMessage } from 'umi/locale';
 import {
   Row,
   Col,
@@ -51,11 +51,10 @@ for (let i = 0; i < 7; i += 1) {
 class Analysis extends Component {
   constructor(props) {
     super(props);
-    const { intl } = props;
     this.rankingListData = [];
     for (let i = 0; i < 7; i += 1) {
       this.rankingListData.push({
-        title: intl.formatMessage({ id: 'app.analysis.test' }, { no: i }),
+        title: formatMessage({ id: 'app.analysis.test' }, { no: i }),
         total: 323234,
       });
     }
@@ -657,4 +656,4 @@ class Analysis extends Component {
   }
 }
 
-export default injectIntl(Analysis);
+export default Analysis;

+ 4 - 5
src/pages/layouts/BasicLayout.js

@@ -3,13 +3,13 @@
 import React from 'react';
 import { Layout } from 'antd';
 import DocumentTitle from 'react-document-title';
-import { injectIntl } from 'react-intl';
 import memoizeOne from 'memoize-one';
 import { connect } from 'dva';
 // import { Route, Redirect, Switch } from 'dva/router';
 import { ContainerQuery } from 'react-container-query';
 import classNames from 'classnames';
 import pathToRegexp from 'path-to-regexp';
+import { formatMessage } from 'umi/locale';
 import SiderMenu from '../../components/SiderMenu';
 // import NotFound from '../Exception/404';
 // import { getRoutes } from '../utils/utils';
@@ -21,7 +21,7 @@ import Header from './Header';
 import Context from './MenuContext';
 
 const { Content } = Layout;
-const { AuthorizedRoute, check } = Authorized;
+const { check } = Authorized;
 
 /**
  * 获取面包屑映射
@@ -84,7 +84,6 @@ class BasicLayout extends React.PureComponent {
 
   getPageTitle = pathname => {
     let currRouterData = null;
-    const { intl } = this.props;
     // match params path
     Object.keys(this.breadcrumbNameMap).forEach(key => {
       if (pathToRegexp(key).test(pathname)) {
@@ -94,7 +93,7 @@ class BasicLayout extends React.PureComponent {
     if (!currRouterData) {
       return 'Ant Design Pro';
     }
-    const message = intl.formatMessage({
+    const message = formatMessage({
       id: currRouterData.locale || currRouterData.name,
       defaultMessage: currRouterData.name,
     });
@@ -221,4 +220,4 @@ export default connect(({ global, setting }) => ({
   collapsed: global.collapsed,
   layout: setting.layout,
   ...setting,
-}))(injectIntl(BasicLayout));
+}))(BasicLayout);

+ 1 - 1
src/pages/layouts/PageHeaderLayout.js

@@ -1,5 +1,5 @@
 import React from 'react';
-import { FormattedMessage } from 'react-intl';
+import { FormattedMessage } from 'umi/locale';
 import { Link } from 'dva/router';
 import PageHeader from '../../components/PageHeader';
 import GridContent from './GridContent';