陈帅 преди 6 години
родител
ревизия
3764485290
променени са 48 файла, в които са добавени 13 реда и са изтрити 3813 реда
  1. 10 11
      config/config.ts
  2. 3 1
      package.json
  3. 0 197
      src/pages/analysis/_mock.ts
  4. 0 135
      src/pages/analysis/components/Charts/Bar/index.tsx
  5. 0 75
      src/pages/analysis/components/Charts/ChartCard/index.less
  6. 0 98
      src/pages/analysis/components/Charts/ChartCard/index.tsx
  7. 0 17
      src/pages/analysis/components/Charts/Field/index.less
  8. 0 18
      src/pages/analysis/components/Charts/Field/index.tsx
  9. 0 177
      src/pages/analysis/components/Charts/Gauge/index.tsx
  10. 0 133
      src/pages/analysis/components/Charts/MiniArea/index.tsx
  11. 0 61
      src/pages/analysis/components/Charts/MiniBar/index.tsx
  12. 0 37
      src/pages/analysis/components/Charts/MiniProgress/index.less
  13. 0 43
      src/pages/analysis/components/Charts/MiniProgress/index.tsx
  14. 0 94
      src/pages/analysis/components/Charts/Pie/index.less
  15. 0 306
      src/pages/analysis/components/Charts/Pie/index.tsx
  16. 0 6
      src/pages/analysis/components/Charts/TagCloud/index.less
  17. 0 206
      src/pages/analysis/components/Charts/TagCloud/index.tsx
  18. 0 3
      src/pages/analysis/components/Charts/TimelineChart/index.less
  19. 0 133
      src/pages/analysis/components/Charts/TimelineChart/index.tsx
  20. 0 28
      src/pages/analysis/components/Charts/WaterWave/index.less
  21. 0 230
      src/pages/analysis/components/Charts/WaterWave/index.tsx
  22. 0 75
      src/pages/analysis/components/Charts/autoHeight.tsx
  23. 0 3
      src/pages/analysis/components/Charts/bizcharts.d.ts
  24. 0 3
      src/pages/analysis/components/Charts/bizcharts.tsx
  25. 0 19
      src/pages/analysis/components/Charts/index.less
  26. 0 45
      src/pages/analysis/components/Charts/index.tsx
  27. 0 162
      src/pages/analysis/components/IntroduceRow.tsx
  28. 0 68
      src/pages/analysis/components/NumberInfo/index.less
  29. 0 61
      src/pages/analysis/components/NumberInfo/index.tsx
  30. 0 82
      src/pages/analysis/components/OfflineData.tsx
  31. 0 10
      src/pages/analysis/components/PageLoading/index.tsx
  32. 0 79
      src/pages/analysis/components/ProportionSales.tsx
  33. 0 162
      src/pages/analysis/components/SalesCard.tsx
  34. 0 128
      src/pages/analysis/components/TopSearch.tsx
  35. 0 37
      src/pages/analysis/components/Trend/index.less
  36. 0 42
      src/pages/analysis/components/Trend/index.tsx
  37. 0 67
      src/pages/analysis/data.d.ts
  38. 0 215
      src/pages/analysis/index.tsx
  39. 0 34
      src/pages/analysis/locales/en-US.ts
  40. 0 34
      src/pages/analysis/locales/pt-BR.ts
  41. 0 34
      src/pages/analysis/locales/zh-CN.ts
  42. 0 34
      src/pages/analysis/locales/zh-TW.ts
  43. 0 84
      src/pages/analysis/model.tsx
  44. 0 5
      src/pages/analysis/service.tsx
  45. 0 185
      src/pages/analysis/style.less
  46. 0 33
      src/pages/analysis/utils/Yuan.tsx
  47. 0 50
      src/pages/analysis/utils/utils.less
  48. 0 53
      src/pages/analysis/utils/utils.ts

+ 10 - 11
config/config.ts

@@ -4,12 +4,10 @@ import slash from 'slash2';
 import { IPlugin, IConfig } from 'umi-types';
 import defaultSettings from './defaultSettings';
 import webpackPlugin from './plugin.config';
-
-const { pwa, primaryColor } = defaultSettings;
-// preview.pro.ant.design only do not use in your production ;
+const { pwa, primaryColor } = defaultSettings; // preview.pro.ant.design only do not use in your production ;
 // preview.pro.ant.design 专用环境变量,请不要在你的项目中使用它。
-const { ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION, TEST, NODE_ENV } = process.env;
 
+const { ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION, TEST, NODE_ENV } = process.env;
 const plugins: IPlugin[] = [
   [
     'umi-plugin-react',
@@ -59,10 +57,9 @@ const plugins: IPlugin[] = [
       autoAddMenu: true,
     },
   ],
-];
-
-// 针对 preview.pro.ant.design 的 GA 统计代码
+]; // 针对 preview.pro.ant.design 的 GA 统计代码
 // preview.pro.ant.design only do not use in your production ; preview.pro.ant.design 专用环境变量,请不要在你的项目中使用它。
+
 if (ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION === 'site') {
   plugins.push([
     'umi-plugin-ga',
@@ -84,7 +81,6 @@ const uglifyJSOptions =
         },
       }
     : {};
-
 export default {
   // add for transfer to umi
   plugins,
@@ -107,9 +103,9 @@ export default {
       routes: [
         {
           path: '/',
-          name: 'Analysis',
-          icon: 'dashboard',
-          component: './analysis',
+          name: 'welcome',
+          icon: 'smile',
+          component: './Welcome',
         },
       ],
     },
@@ -147,7 +143,9 @@ export default {
       ) {
         return localName;
       }
+
       const match = context.resourcePath.match(/src(.*)/);
+
       if (match && match[1]) {
         const antdProPath = match[1].replace('.less', '');
         const arr = slash(antdProPath)
@@ -156,6 +154,7 @@ export default {
           .map((a: string) => a.toLowerCase());
         return `antd-pro${arr.join('-')}-${localName}`.replace(/--/g, '-');
       }
+
       return localName;
     },
   },

+ 3 - 1
package.json

@@ -61,6 +61,7 @@
     "bizcharts-plugin-slider": "^2.1.1-beta.1",
     "classnames": "^2.2.6",
     "dva": "^2.4.0",
+    "hash.js": "^1.1.5",
     "lodash": "^4.17.10",
     "lodash-decorators": "^6.0.0",
     "memoize-one": "^5.0.0",
@@ -77,7 +78,8 @@
     "react-dom": "^16.7.0",
     "react-fittext": "^1.0.0",
     "react-media": "^1.9.2",
-    "react-media-hook2": "^1.0.2"
+    "react-media-hook2": "^1.0.2",
+    "umi": "^2.7.0-beta.2"
   },
   "devDependencies": {
     "@types/classnames": "^2.2.7",

+ 0 - 197
src/pages/analysis/_mock.ts

@@ -1,197 +0,0 @@
-import moment from 'moment';
-import { IVisitData, IRadarData, IAnalysisData } from './data';
-
-// mock data
-const visitData: IVisitData[] = [];
-const beginDay = new Date().getTime();
-
-const fakeY = [7, 5, 4, 2, 4, 7, 5, 6, 5, 9, 6, 3, 1, 5, 3, 6, 5];
-for (let i = 0; i < fakeY.length; i += 1) {
-  visitData.push({
-    x: moment(new Date(beginDay + 1000 * 60 * 60 * 24 * i)).format('YYYY-MM-DD'),
-    y: fakeY[i],
-  });
-}
-
-const visitData2 = [];
-const fakeY2 = [1, 6, 4, 8, 3, 7, 2];
-for (let i = 0; i < fakeY2.length; i += 1) {
-  visitData2.push({
-    x: moment(new Date(beginDay + 1000 * 60 * 60 * 24 * i)).format('YYYY-MM-DD'),
-    y: fakeY2[i],
-  });
-}
-
-const salesData = [];
-for (let i = 0; i < 12; i += 1) {
-  salesData.push({
-    x: `${i + 1}月`,
-    y: Math.floor(Math.random() * 1000) + 200,
-  });
-}
-const searchData = [];
-for (let i = 0; i < 50; i += 1) {
-  searchData.push({
-    index: i + 1,
-    keyword: `搜索关键词-${i}`,
-    count: Math.floor(Math.random() * 1000),
-    range: Math.floor(Math.random() * 100),
-    status: Math.floor((Math.random() * 10) % 2),
-  });
-}
-const salesTypeData = [
-  {
-    x: '家用电器',
-    y: 4544,
-  },
-  {
-    x: '食用酒水',
-    y: 3321,
-  },
-  {
-    x: '个护健康',
-    y: 3113,
-  },
-  {
-    x: '服饰箱包',
-    y: 2341,
-  },
-  {
-    x: '母婴产品',
-    y: 1231,
-  },
-  {
-    x: '其他',
-    y: 1231,
-  },
-];
-
-const salesTypeDataOnline = [
-  {
-    x: '家用电器',
-    y: 244,
-  },
-  {
-    x: '食用酒水',
-    y: 321,
-  },
-  {
-    x: '个护健康',
-    y: 311,
-  },
-  {
-    x: '服饰箱包',
-    y: 41,
-  },
-  {
-    x: '母婴产品',
-    y: 121,
-  },
-  {
-    x: '其他',
-    y: 111,
-  },
-];
-
-const salesTypeDataOffline = [
-  {
-    x: '家用电器',
-    y: 99,
-  },
-  {
-    x: '食用酒水',
-    y: 188,
-  },
-  {
-    x: '个护健康',
-    y: 344,
-  },
-  {
-    x: '服饰箱包',
-    y: 255,
-  },
-  {
-    x: '其他',
-    y: 65,
-  },
-];
-
-const offlineData = [];
-for (let i = 0; i < 10; i += 1) {
-  offlineData.push({
-    name: `Stores ${i}`,
-    cvr: Math.ceil(Math.random() * 9) / 10,
-  });
-}
-const offlineChartData = [];
-for (let i = 0; i < 20; i += 1) {
-  offlineChartData.push({
-    x: new Date().getTime() + 1000 * 60 * 30 * i,
-    y1: Math.floor(Math.random() * 100) + 10,
-    y2: Math.floor(Math.random() * 100) + 10,
-  });
-}
-
-const radarOriginData = [
-  {
-    name: '个人',
-    ref: 10,
-    koubei: 8,
-    output: 4,
-    contribute: 5,
-    hot: 7,
-  },
-  {
-    name: '团队',
-    ref: 3,
-    koubei: 9,
-    output: 6,
-    contribute: 3,
-    hot: 1,
-  },
-  {
-    name: '部门',
-    ref: 4,
-    koubei: 1,
-    output: 6,
-    contribute: 5,
-    hot: 7,
-  },
-];
-
-const radarData: IRadarData[] = [];
-const radarTitleMap = {
-  ref: '引用',
-  koubei: '口碑',
-  output: '产量',
-  contribute: '贡献',
-  hot: '热度',
-};
-radarOriginData.forEach(item => {
-  Object.keys(item).forEach(key => {
-    if (key !== 'name') {
-      radarData.push({
-        name: item.name,
-        label: radarTitleMap[key],
-        value: item[key],
-      });
-    }
-  });
-});
-
-const getFakeChartData: IAnalysisData = {
-  visitData,
-  visitData2,
-  salesData,
-  searchData,
-  offlineData,
-  offlineChartData,
-  salesTypeData,
-  salesTypeDataOnline,
-  salesTypeDataOffline,
-  radarData,
-};
-
-export default {
-  'GET /api/analysis/fake_chart_data': getFakeChartData,
-};

+ 0 - 135
src/pages/analysis/components/Charts/Bar/index.tsx

@@ -1,135 +0,0 @@
-import React, { Component } from 'react';
-import { Chart, Axis, Tooltip, Geom } from 'bizcharts';
-import Debounce from 'lodash-decorators/debounce';
-import Bind from 'lodash-decorators/bind';
-import styles from '../index.less';
-import autoHeight from '../autoHeight';
-
-export interface IBarProps {
-  title: React.ReactNode;
-  color?: string;
-  padding?: [number, number, number, number];
-  height?: number;
-  data: Array<{
-    x: string;
-    y: number;
-  }>;
-  forceFit?: boolean;
-  autoLabel?: boolean;
-  style?: React.CSSProperties;
-}
-
-class Bar extends Component<
-  IBarProps,
-  {
-    autoHideXLabels: boolean;
-  }
-> {
-  root: HTMLDivElement | undefined;
-  node: HTMLDivElement | undefined;
-
-  state = {
-    height: 0,
-    autoHideXLabels: false,
-  };
-
-  componentDidMount() {
-    window.addEventListener('resize', this.resize, { passive: true });
-  }
-
-  componentWillUnmount() {
-    window.removeEventListener('resize', this.resize);
-  }
-
-  handleRoot = (n: HTMLDivElement) => {
-    this.root = n;
-  };
-  handleRef = (n: HTMLDivElement) => {
-    this.node = n;
-  };
-
-  @Bind()
-  @Debounce(400)
-  resize() {
-    if (!this.node || !this.node.parentNode) {
-      return;
-    }
-    const canvasWidth = (this.node.parentNode as HTMLDivElement).clientWidth;
-    const { data = [], autoLabel = true } = this.props;
-    if (!autoLabel) {
-      return;
-    }
-    const minWidth = data.length * 30;
-    const { autoHideXLabels } = this.state;
-
-    if (canvasWidth <= minWidth) {
-      if (!autoHideXLabels) {
-        this.setState({
-          autoHideXLabels: true,
-        });
-      }
-    } else if (autoHideXLabels) {
-      this.setState({
-        autoHideXLabels: false,
-      });
-    }
-  }
-
-  render() {
-    const {
-      height: propsHeight = 1,
-      title,
-      forceFit = true,
-      data,
-      color = 'rgba(24, 144, 255, 0.85)',
-      padding,
-    } = this.props;
-
-    const { autoHideXLabels } = this.state;
-
-    const scale = {
-      x: {
-        type: 'cat',
-      },
-      y: {
-        min: 0,
-      },
-    };
-
-    const tooltip: [string, (...args: any[]) => { name?: string; value: string }] = [
-      'x*y',
-      (x: string, y: string) => ({
-        name: x,
-        value: y,
-      }),
-    ];
-    const { height: stateHeight } = this.state;
-    const height = propsHeight || stateHeight;
-    return (
-      <div className={styles.chart} style={{ height }} ref={this.handleRoot}>
-        <div ref={this.handleRef}>
-          {title && <h4 style={{ marginBottom: 20 }}>{title}</h4>}
-          <Chart
-            scale={scale}
-            height={title ? height - 41 : height}
-            forceFit={forceFit}
-            data={data}
-            padding={padding || 'auto'}
-          >
-            <Axis
-              name="x"
-              title={false}
-              label={autoHideXLabels ? false : {}}
-              tickLine={autoHideXLabels ? false : {}}
-            />
-            <Axis name="y" min={0} />
-            <Tooltip showTitle={false} crosshairs={false} />
-            <Geom type="interval" position="x*y" color={color} tooltip={tooltip} />
-          </Chart>
-        </div>
-      </div>
-    );
-  }
-}
-
-export default autoHeight()(Bar);

+ 0 - 75
src/pages/analysis/components/Charts/ChartCard/index.less

@@ -1,75 +0,0 @@
-@import '~antd/lib/style/themes/default.less';
-
-.chartCard {
-  position: relative;
-  .chartTop {
-    position: relative;
-    width: 100%;
-    overflow: hidden;
-  }
-  .chartTopMargin {
-    margin-bottom: 12px;
-  }
-  .chartTopHasMargin {
-    margin-bottom: 20px;
-  }
-  .metaWrap {
-    float: left;
-  }
-  .avatar {
-    position: relative;
-    top: 4px;
-    float: left;
-    margin-right: 20px;
-    img {
-      border-radius: 100%;
-    }
-  }
-  .meta {
-    height: 22px;
-    color: @text-color-secondary;
-    font-size: @font-size-base;
-    line-height: 22px;
-  }
-  .action {
-    position: absolute;
-    top: 4px;
-    right: 0;
-    line-height: 1;
-    cursor: pointer;
-  }
-  .total {
-    height: 38px;
-    margin-top: 4px;
-    margin-bottom: 0;
-    overflow: hidden;
-    color: @heading-color;
-    font-size: 30px;
-    line-height: 38px;
-    white-space: nowrap;
-    text-overflow: ellipsis;
-    word-break: break-all;
-  }
-  .content {
-    position: relative;
-    width: 100%;
-    margin-bottom: 12px;
-  }
-  .contentFixed {
-    position: absolute;
-    bottom: 0;
-    left: 0;
-    width: 100%;
-  }
-  .footer {
-    margin-top: 8px;
-    padding-top: 9px;
-    border-top: 1px solid @border-color-split;
-    & > * {
-      position: relative;
-    }
-  }
-  .footerMargin {
-    margin-top: 20px;
-  }
-}

+ 0 - 98
src/pages/analysis/components/Charts/ChartCard/index.tsx

@@ -1,98 +0,0 @@
-import React from 'react';
-import { Card } from 'antd';
-import classNames from 'classnames';
-import { CardProps } from 'antd/lib/card';
-
-import styles from './index.less';
-
-type totalType = () => React.ReactNode;
-
-const renderTotal = (total?: number | totalType | React.ReactNode) => {
-  if (!total) {
-    return;
-  }
-  let totalDom;
-  switch (typeof total) {
-    case 'undefined':
-      totalDom = null;
-      break;
-    case 'function':
-      totalDom = <div className={styles.total}>{total()}</div>;
-      break;
-    default:
-      totalDom = <div className={styles.total}>{total}</div>;
-  }
-  return totalDom;
-};
-
-export interface IChartCardProps extends CardProps {
-  title: React.ReactNode;
-  action?: React.ReactNode;
-  total?: React.ReactNode | number | (() => React.ReactNode | number);
-  footer?: React.ReactNode;
-  contentHeight?: number;
-  avatar?: React.ReactNode;
-  style?: React.CSSProperties;
-}
-
-class ChartCard extends React.Component<IChartCardProps> {
-  renderContent = () => {
-    const { contentHeight, title, avatar, action, total, footer, children, loading } = this.props;
-    if (loading) {
-      return false;
-    }
-    return (
-      <div className={styles.chartCard}>
-        <div
-          className={classNames(styles.chartTop, {
-            [styles.chartTopMargin]: !children && !footer,
-          })}
-        >
-          <div className={styles.avatar}>{avatar}</div>
-          <div className={styles.metaWrap}>
-            <div className={styles.meta}>
-              <span className={styles.title}>{title}</span>
-              <span className={styles.action}>{action}</span>
-            </div>
-            {renderTotal(total)}
-          </div>
-        </div>
-        {children && (
-          <div className={styles.content} style={{ height: contentHeight || 'auto' }}>
-            <div className={contentHeight && styles.contentFixed}>{children}</div>
-          </div>
-        )}
-        {footer && (
-          <div
-            className={classNames(styles.footer, {
-              [styles.footerMargin]: !children,
-            })}
-          >
-            {footer}
-          </div>
-        )}
-      </div>
-    );
-  };
-
-  render() {
-    const {
-      loading = false,
-      contentHeight,
-      title,
-      avatar,
-      action,
-      total,
-      footer,
-      children,
-      ...rest
-    } = this.props;
-    return (
-      <Card loading={loading} bodyStyle={{ padding: '20px 24px 8px 24px' }} {...rest}>
-        {this.renderContent()}
-      </Card>
-    );
-  }
-}
-
-export default ChartCard;

+ 0 - 17
src/pages/analysis/components/Charts/Field/index.less

@@ -1,17 +0,0 @@
-@import '~antd/lib/style/themes/default.less';
-
-.field {
-  margin: 0;
-  overflow: hidden;
-  white-space: nowrap;
-  text-overflow: ellipsis;
-  .label,
-  .number {
-    font-size: @font-size-base;
-    line-height: 22px;
-  }
-  .number {
-    margin-left: 8px;
-    color: @heading-color;
-  }
-}

+ 0 - 18
src/pages/analysis/components/Charts/Field/index.tsx

@@ -1,18 +0,0 @@
-import React from 'react';
-
-import styles from './index.less';
-
-export interface IFieldProps {
-  label: React.ReactNode;
-  value: React.ReactNode;
-  style?: React.CSSProperties;
-}
-
-const Field: React.SFC<IFieldProps> = ({ label, value, ...rest }) => (
-  <div className={styles.field} {...rest}>
-    <span className={styles.label}>{label}</span>
-    <span className={styles.number}>{value}</span>
-  </div>
-);
-
-export default Field;

+ 0 - 177
src/pages/analysis/components/Charts/Gauge/index.tsx

@@ -1,177 +0,0 @@
-import React from 'react';
-import { Chart, Geom, Axis, Coord, Guide, Shape } from 'bizcharts';
-import autoHeight from '../autoHeight';
-
-const { Arc, Html, Line } = Guide;
-
-export interface IGaugeProps {
-  title: React.ReactNode;
-  color?: string;
-  height?: number;
-  bgColor?: number;
-  percent: number;
-  forceFit?: boolean;
-  style?: React.CSSProperties;
-  formatter: (value: string) => string;
-}
-
-const defaultFormatter = (val: string): string => {
-  switch (val) {
-    case '2':
-      return '差';
-    case '4':
-      return '中';
-    case '6':
-      return '良';
-    case '8':
-      return '优';
-    default:
-      return '';
-  }
-};
-
-Shape.registerShape!('point', 'pointer', {
-  drawShape(cfg: any, group: any) {
-    let point = cfg.points[0];
-    point = (this as any).parsePoint(point);
-    const center = (this as any).parsePoint({
-      x: 0,
-      y: 0,
-    });
-    group.addShape('line', {
-      attrs: {
-        x1: center.x,
-        y1: center.y,
-        x2: point.x,
-        y2: point.y,
-        stroke: cfg.color,
-        lineWidth: 2,
-        lineCap: 'round',
-      },
-    });
-    return group.addShape('circle', {
-      attrs: {
-        x: center.x,
-        y: center.y,
-        r: 6,
-        stroke: cfg.color,
-        lineWidth: 3,
-        fill: '#fff',
-      },
-    });
-  },
-});
-
-class Gauge extends React.Component<IGaugeProps> {
-  render() {
-    const {
-      title,
-      height = 1,
-      percent,
-      forceFit = true,
-      formatter = defaultFormatter,
-      color = '#2F9CFF',
-      bgColor = '#F0F2F5',
-    } = this.props;
-    const cols = {
-      value: {
-        type: 'linear',
-        min: 0,
-        max: 10,
-        tickCount: 6,
-        nice: true,
-      },
-    };
-    const renderHtml = () => `
-    <div style="width: 300px;text-align: center;font-size: 12px!important;">
-      <p style="font-size: 14px; color: rgba(0,0,0,0.43);margin: 0;">${title}</p>
-      <p style="font-size: 24px;color: rgba(0,0,0,0.85);margin: 0;">
-        ${(data[0].value * 10).toFixed(2)}%
-      </p>
-    </div>`;
-    const data = [{ value: percent / 10 }];
-    const textStyle: {
-      fontSize: number;
-      fill: string;
-      textAlign: 'center';
-    } = {
-      fontSize: 12,
-      fill: 'rgba(0, 0, 0, 0.65)',
-      textAlign: 'center',
-    };
-    return (
-      <Chart height={height} data={data} scale={cols} padding={[-16, 0, 16, 0]} forceFit={forceFit}>
-        <Coord type="polar" startAngle={-1.25 * Math.PI} endAngle={0.25 * Math.PI} radius={0.8} />
-        <Axis name="1" line={undefined} />
-        <Axis
-          line={undefined}
-          tickLine={undefined}
-          subTickLine={undefined}
-          name="value"
-          zIndex={2}
-          label={{
-            offset: -12,
-            formatter,
-            textStyle: textStyle,
-          }}
-        />
-        <Guide>
-          <Line
-            start={[3, 0.905]}
-            end={[3, 0.85]}
-            lineStyle={{
-              stroke: color,
-              lineDash: undefined,
-              lineWidth: 2,
-            }}
-          />
-          <Line
-            start={[5, 0.905]}
-            end={[5, 0.85]}
-            lineStyle={{
-              stroke: color,
-              lineDash: undefined,
-              lineWidth: 3,
-            }}
-          />
-          <Line
-            start={[7, 0.905]}
-            end={[7, 0.85]}
-            lineStyle={{
-              stroke: color,
-              lineDash: undefined,
-              lineWidth: 3,
-            }}
-          />
-          <Arc
-            start={[0, 0.965]}
-            end={[10, 0.965]}
-            style={{
-              stroke: bgColor,
-              lineWidth: 10,
-            }}
-          />
-          <Arc
-            start={[0, 0.965]}
-            end={[data[0].value, 0.965]}
-            style={{
-              stroke: color,
-              lineWidth: 10,
-            }}
-          />
-          <Html position={['50%', '95%']} html={renderHtml()} />
-        </Guide>
-        <Geom
-          line={false}
-          type="point"
-          position="value*1"
-          shape="pointer"
-          color={color}
-          active={false}
-        />
-      </Chart>
-    );
-  }
-}
-
-export default autoHeight()(Gauge);

+ 0 - 133
src/pages/analysis/components/Charts/MiniArea/index.tsx

@@ -1,133 +0,0 @@
-import React from 'react';
-import { Chart, Axis, Tooltip, Geom } from 'bizcharts';
-import autoHeight from '../autoHeight';
-import styles from '../index.less';
-
-export interface IAxis {
-  title: any;
-  line: any;
-  gridAlign: any;
-  labels: any;
-  tickLine: any;
-  grid: any;
-}
-
-export interface IMiniAreaProps {
-  color?: string;
-  height?: number;
-  borderColor?: string;
-  line?: boolean;
-  animate?: boolean;
-  xAxis?: IAxis;
-  forceFit?: boolean;
-  scale?: { x: any; y: any };
-  yAxis?: IAxis;
-  borderWidth?: number;
-  data: Array<{
-    x: number | string;
-    y: number;
-  }>;
-}
-
-class MiniArea extends React.Component<IMiniAreaProps> {
-  render() {
-    const {
-      height = 1,
-      data = [],
-      forceFit = true,
-      color = 'rgba(24, 144, 255, 0.2)',
-      borderColor = '#1089ff',
-      scale = { x: {}, y: {} },
-      borderWidth = 2,
-      line,
-      xAxis,
-      yAxis,
-      animate = true,
-    } = this.props;
-
-    const padding: [number, number, number, number] = [36, 5, 30, 5];
-
-    const scaleProps = {
-      x: {
-        type: 'cat',
-        range: [0, 1],
-        ...scale!.x,
-      },
-      y: {
-        min: 0,
-        ...scale!.y,
-      },
-    };
-
-    const tooltip: [string, (...args: any[]) => { name?: string; value: string }] = [
-      'x*y',
-      (x: string, y: string) => ({
-        name: x,
-        value: y,
-      }),
-    ];
-
-    const chartHeight = height + 54;
-
-    return (
-      <div className={styles.miniChart} style={{ height }}>
-        <div className={styles.chartContent}>
-          {height > 0 && (
-            <Chart
-              animate={animate}
-              scale={scaleProps}
-              height={chartHeight}
-              forceFit={forceFit}
-              data={data}
-              padding={padding}
-            >
-              <Axis
-                key="axis-x"
-                name="x"
-                label={false}
-                line={false}
-                tickLine={false}
-                grid={false}
-                {...xAxis}
-              />
-              <Axis
-                key="axis-y"
-                name="y"
-                label={false}
-                line={false}
-                tickLine={false}
-                grid={false}
-                {...yAxis}
-              />
-              <Tooltip showTitle={false} crosshairs={false} />
-              <Geom
-                type="area"
-                position="x*y"
-                color={color}
-                tooltip={tooltip}
-                shape="smooth"
-                style={{
-                  fillOpacity: 1,
-                }}
-              />
-              {line ? (
-                <Geom
-                  type="line"
-                  position="x*y"
-                  shape="smooth"
-                  color={borderColor}
-                  size={borderWidth}
-                  tooltip={false}
-                />
-              ) : (
-                <span style={{ display: 'none' }} />
-              )}
-            </Chart>
-          )}
-        </div>
-      </div>
-    );
-  }
-}
-
-export default autoHeight()(MiniArea);

+ 0 - 61
src/pages/analysis/components/Charts/MiniBar/index.tsx

@@ -1,61 +0,0 @@
-import React from 'react';
-import { Chart, Tooltip, Geom } from 'bizcharts';
-import autoHeight from '../autoHeight';
-import styles from '../index.less';
-
-export interface IMiniBarProps {
-  color?: string;
-  height?: number;
-  data: Array<{
-    x: number | string;
-    y: number;
-  }>;
-  forceFit?: boolean;
-  style?: React.CSSProperties;
-}
-
-class MiniBar extends React.Component<IMiniBarProps> {
-  render() {
-    const { height = 0, forceFit = true, color = '#1890FF', data = [] } = this.props;
-
-    const scale = {
-      x: {
-        type: 'cat',
-      },
-      y: {
-        min: 0,
-      },
-    };
-
-    const padding: [number, number, number, number] = [36, 5, 30, 5];
-
-    const tooltip: [string, (...args: any[]) => { name?: string; value: string }] = [
-      'x*y',
-      (x: string, y: string) => ({
-        name: x,
-        value: y,
-      }),
-    ];
-
-    // for tooltip not to be hide
-    const chartHeight = height + 54;
-
-    return (
-      <div className={styles.miniChart} style={{ height }}>
-        <div className={styles.chartContent}>
-          <Chart
-            scale={scale}
-            height={chartHeight}
-            forceFit={forceFit}
-            data={data}
-            padding={padding}
-          >
-            <Tooltip showTitle={false} crosshairs={false} />
-            <Geom type="interval" position="x*y" color={color} tooltip={tooltip} />
-          </Chart>
-        </div>
-      </div>
-    );
-  }
-}
-export default autoHeight()(MiniBar);

+ 0 - 37
src/pages/analysis/components/Charts/MiniProgress/index.less

@@ -1,37 +0,0 @@
-@import '~antd/lib/style/themes/default.less';
-
-.miniProgress {
-  position: relative;
-  width: 100%;
-  padding: 5px 0;
-  .progressWrap {
-    position: relative;
-    background-color: @background-color-base;
-  }
-  .progress {
-    width: 0;
-    height: 100%;
-    background-color: @primary-color;
-    border-radius: 1px 0 0 1px;
-    transition: all 0.4s cubic-bezier(0.08, 0.82, 0.17, 1) 0s;
-  }
-  .target {
-    position: absolute;
-    top: 0;
-    bottom: 0;
-    z-index: 9;
-    width: 20px;
-    span {
-      position: absolute;
-      top: 0;
-      left: 0;
-      width: 2px;
-      height: 4px;
-      border-radius: 100px;
-    }
-    span:last-child {
-      top: auto;
-      bottom: 0;
-    }
-  }
-}

+ 0 - 43
src/pages/analysis/components/Charts/MiniProgress/index.tsx

@@ -1,43 +0,0 @@
-import React from 'react';
-import { Tooltip } from 'antd';
-import styles from './index.less';
-
-export interface IMiniProgressProps {
-  target: number;
-  targetLabel?: string;
-  color?: string;
-  strokeWidth?: number;
-  percent?: number;
-  style?: React.CSSProperties;
-}
-
-const MiniProgress: React.SFC<IMiniProgressProps> = ({
-  targetLabel,
-  target,
-  color = 'rgb(19, 194, 194)',
-  strokeWidth,
-  percent,
-}) => {
-  return (
-    <div className={styles.miniProgress}>
-      <Tooltip title={targetLabel}>
-        <div className={styles.target} style={{ left: target ? `${target}%` : undefined }}>
-          <span style={{ backgroundColor: color || undefined }} />
-          <span style={{ backgroundColor: color || undefined }} />
-        </div>
-      </Tooltip>
-      <div className={styles.progressWrap}>
-        <div
-          className={styles.progress}
-          style={{
-            backgroundColor: color || undefined,
-            width: percent ? `${percent}%` : undefined,
-            height: strokeWidth || undefined,
-          }}
-        />
-      </div>
-    </div>
-  );
-};
-
-export default MiniProgress;

+ 0 - 94
src/pages/analysis/components/Charts/Pie/index.less

@@ -1,94 +0,0 @@
-@import '~antd/lib/style/themes/default.less';
-
-.pie {
-  position: relative;
-  .chart {
-    position: relative;
-  }
-  &.hasLegend .chart {
-    width: ~'calc(100% - 240px)';
-  }
-  .legend {
-    position: absolute;
-    top: 50%;
-    right: 0;
-    min-width: 200px;
-    margin: 0 20px;
-    padding: 0;
-    list-style: none;
-    transform: translateY(-50%);
-    li {
-      height: 22px;
-      margin-bottom: 16px;
-      line-height: 22px;
-      cursor: pointer;
-      &:last-child {
-        margin-bottom: 0;
-      }
-    }
-  }
-  .dot {
-    position: relative;
-    top: -1px;
-    display: inline-block;
-    width: 8px;
-    height: 8px;
-    margin-right: 8px;
-    border-radius: 8px;
-  }
-  .line {
-    display: inline-block;
-    width: 1px;
-    height: 16px;
-    margin-right: 8px;
-    background-color: @border-color-split;
-  }
-  .legendTitle {
-    color: @text-color;
-  }
-  .percent {
-    color: @text-color-secondary;
-  }
-  .value {
-    position: absolute;
-    right: 0;
-  }
-  .title {
-    margin-bottom: 8px;
-  }
-  .total {
-    position: absolute;
-    top: 50%;
-    left: 50%;
-    max-height: 62px;
-    text-align: center;
-    transform: translate(-50%, -50%);
-    & > h4 {
-      height: 22px;
-      margin-bottom: 8px;
-      color: @text-color-secondary;
-      font-weight: normal;
-      font-size: 14px;
-      line-height: 22px;
-    }
-    & > p {
-      display: block;
-      height: 32px;
-      color: @heading-color;
-      font-size: 1.2em;
-      line-height: 32px;
-      white-space: nowrap;
-    }
-  }
-}
-
-.legendBlock {
-  &.hasLegend .chart {
-    width: 100%;
-    margin: 0 0 32px 0;
-  }
-  .legend {
-    position: relative;
-    transform: none;
-  }
-}

+ 0 - 306
src/pages/analysis/components/Charts/Pie/index.tsx

@@ -1,306 +0,0 @@
-import React, { Component } from 'react';
-import { Chart, Tooltip, Geom, Coord } from 'bizcharts';
-import { DataView } from '@antv/data-set';
-import { Divider } from 'antd';
-import classNames from 'classnames';
-import ReactFitText from 'react-fittext';
-import Debounce from 'lodash-decorators/debounce';
-import Bind from 'lodash-decorators/bind';
-import styles from './index.less';
-import autoHeight from '../autoHeight';
-export interface IPieProps {
-  animate?: boolean;
-  color?: string;
-  colors?: string[];
-  selected?: boolean;
-  height?: number;
-  margin?: [number, number, number, number];
-  hasLegend?: boolean;
-  padding?: [number, number, number, number];
-  percent?: number;
-  data?: Array<{
-    x: string | string;
-    y: number;
-  }>;
-  inner?: number;
-  lineWidth?: number;
-  forceFit?: boolean;
-  style?: React.CSSProperties;
-  className?: string;
-  total?: React.ReactNode | number | (() => React.ReactNode | number);
-  title?: React.ReactNode;
-  tooltip?: boolean;
-  valueFormat?: (value: string) => string | React.ReactNode;
-  subTitle?: React.ReactNode;
-}
-interface IPieState {
-  legendData: Array<{ checked: boolean; x: string; color: string; percent: number; y: string }>;
-  legendBlock: boolean;
-}
-class Pie extends Component<IPieProps, IPieState> {
-  state: IPieState = {
-    legendData: [],
-    legendBlock: false,
-  };
-
-  requestRef: number | undefined;
-  root!: HTMLDivElement;
-  chart: G2.Chart | undefined;
-
-  componentDidMount() {
-    window.addEventListener(
-      'resize',
-      () => {
-        this.requestRef = requestAnimationFrame(() => this.resize());
-      },
-      { passive: true },
-    );
-  }
-
-  componentDidUpdate(preProps: IPieProps) {
-    const { data } = this.props;
-    if (data !== preProps.data) {
-      // because of charts data create when rendered
-      // so there is a trick for get rendered time
-      this.getLegendData();
-    }
-  }
-
-  componentWillUnmount() {
-    if (this.requestRef) {
-      window.cancelAnimationFrame(this.requestRef);
-    }
-    window.removeEventListener('resize', this.resize);
-    if (this.resize) {
-      (this.resize as any).cancel();
-    }
-  }
-
-  getG2Instance = (chart: G2.Chart) => {
-    this.chart = chart;
-    requestAnimationFrame(() => {
-      this.getLegendData();
-      this.resize();
-    });
-  };
-
-  // for custom lengend view
-  getLegendData = () => {
-    if (!this.chart) return;
-    const geom = this.chart.getAllGeoms()[0]; // 获取所有的图形
-    if (!geom) return;
-    const items = geom.get('dataArray') || []; // 获取图形对应的
-
-    const legendData = items.map((item: { color: any; _origin: any }[]) => {
-      /* eslint no-underscore-dangle:0 */
-      const origin = item[0]._origin;
-      origin.color = item[0].color;
-      origin.checked = true;
-      return origin;
-    });
-
-    this.setState({
-      legendData,
-    });
-  };
-  handleRoot = (n: HTMLDivElement) => {
-    this.root = n;
-  };
-
-  handleLegendClick = (item: any, i: string | number) => {
-    const newItem = item;
-    newItem.checked = !newItem.checked;
-
-    const { legendData } = this.state;
-    legendData[i] = newItem;
-
-    const filteredLegendData = legendData.filter(l => l.checked).map(l => l.x);
-
-    if (this.chart) {
-      this.chart.filter('x', val => filteredLegendData.indexOf(val + '') > -1);
-    }
-
-    this.setState({
-      legendData,
-    });
-  };
-
-  // for window resize auto responsive legend
-  @Bind()
-  @Debounce(300)
-  resize() {
-    const { hasLegend } = this.props;
-    const { legendBlock } = this.state;
-    if (!hasLegend || !this.root) {
-      window.removeEventListener('resize', this.resize);
-      return;
-    }
-    if (
-      this.root &&
-      this.root.parentNode &&
-      (this.root.parentNode as HTMLElement).clientWidth <= 380
-    ) {
-      if (!legendBlock) {
-        this.setState({
-          legendBlock: true,
-        });
-      }
-    } else if (legendBlock) {
-      this.setState({
-        legendBlock: false,
-      });
-    }
-  }
-
-  render() {
-    const {
-      valueFormat,
-      subTitle,
-      total,
-      hasLegend = false,
-      className,
-      style,
-      height = 0,
-      forceFit = true,
-      percent,
-      color,
-      inner = 0.75,
-      animate = true,
-      colors,
-      lineWidth = 1,
-    } = this.props;
-
-    const { legendData, legendBlock } = this.state;
-    const pieClassName = classNames(styles.pie, className, {
-      [styles.hasLegend]: !!hasLegend,
-      [styles.legendBlock]: legendBlock,
-    });
-
-    const {
-      data: propsData,
-      selected: propsSelected = true,
-      tooltip: propsTooltip = true,
-    } = this.props;
-
-    let data = propsData || [];
-    let selected = propsSelected;
-    let tooltip = propsTooltip;
-
-    const defaultColors = colors;
-    data = data || [];
-    selected = selected || true;
-    tooltip = tooltip || true;
-    let formatColor;
-
-    const scale = {
-      x: {
-        type: 'cat',
-        range: [0, 1],
-      },
-      y: {
-        min: 0,
-      },
-    };
-
-    if (percent || percent === 0) {
-      selected = false;
-      tooltip = false;
-      formatColor = (value: string) => {
-        if (value === '占比') {
-          return color || 'rgba(24, 144, 255, 0.85)';
-        }
-        return '#F0F2F5';
-      };
-
-      data = [
-        {
-          x: '占比',
-          y: parseFloat(percent + ''),
-        },
-        {
-          x: '反比',
-          y: 100 - parseFloat(percent + ''),
-        },
-      ];
-    }
-
-    const tooltipFormat: [string, (...args: any[]) => { name?: string; value: string }] = [
-      'x*percent',
-      (x: string, p: number) => ({
-        name: x,
-        value: `${(p * 100).toFixed(2)}%`,
-      }),
-    ];
-
-    const padding = [12, 0, 12, 0] as [number, number, number, number];
-
-    const dv = new DataView();
-    dv.source(data).transform({
-      type: 'percent',
-      field: 'y',
-      dimension: 'x',
-      as: 'percent',
-    });
-
-    return (
-      <div ref={this.handleRoot} className={pieClassName} style={style}>
-        <ReactFitText maxFontSize={25}>
-          <div className={styles.chart}>
-            <Chart
-              scale={scale}
-              height={height}
-              forceFit={forceFit}
-              data={dv}
-              padding={padding}
-              animate={animate}
-              onGetG2Instance={this.getG2Instance}
-            >
-              {!!tooltip && <Tooltip showTitle={false} />}
-              <Coord type="theta" innerRadius={inner} />
-              <Geom
-                style={{ lineWidth, stroke: '#fff' }}
-                tooltip={tooltip ? tooltipFormat : undefined}
-                type="intervalStack"
-                position="percent"
-                color={['x', percent || percent === 0 ? formatColor : defaultColors] as any}
-                selected={selected}
-              />
-            </Chart>
-
-            {(subTitle || total) && (
-              <div className={styles.total}>
-                {subTitle && <h4 className="pie-sub-title">{subTitle}</h4>}
-                {/* eslint-disable-next-line */}
-                {total && (
-                  <div className="pie-stat">{typeof total === 'function' ? total() : total}</div>
-                )}
-              </div>
-            )}
-          </div>
-        </ReactFitText>
-        {hasLegend && (
-          <ul className={styles.legend}>
-            {legendData.map((item, i) => (
-              <li key={item.x} onClick={() => this.handleLegendClick(item, i)}>
-                <span
-                  className={styles.dot}
-                  style={{
-                    backgroundColor: !item.checked ? '#aaa' : item.color,
-                  }}
-                />
-                <span className={styles.legendTitle}>{item.x}</span>
-                <Divider type="vertical" />
-                <span className={styles.percent}>
-                  {`${(Number.isNaN(item.percent) ? 0 : item.percent * 100).toFixed(2)}%`}
-                </span>
-                <span className={styles.value}>{valueFormat ? valueFormat(item.y) : item.y}</span>
-              </li>
-            ))}
-          </ul>
-        )}
-      </div>
-    );
-  }
-}
-
-export default autoHeight()(Pie);

+ 0 - 6
src/pages/analysis/components/Charts/TagCloud/index.less

@@ -1,6 +0,0 @@
-.tagCloud {
-  overflow: hidden;
-  canvas {
-    transform-origin: 0 0;
-  }
-}

+ 0 - 206
src/pages/analysis/components/Charts/TagCloud/index.tsx

@@ -1,206 +0,0 @@
-import React, { Component } from 'react';
-import { Chart, Geom, Coord, Shape, Tooltip } from 'bizcharts';
-import DataSet from '@antv/data-set';
-import Debounce from 'lodash-decorators/debounce';
-import Bind from 'lodash-decorators/bind';
-import classNames from 'classnames';
-import autoHeight from '../autoHeight';
-import styles from './index.less';
-
-/* eslint no-underscore-dangle: 0 */
-/* eslint no-param-reassign: 0 */
-
-const imgUrl = 'https://gw.alipayobjects.com/zos/rmsportal/gWyeGLCdFFRavBGIDzWk.png';
-
-export interface ITagCloudProps {
-  data: Array<{
-    name: string;
-    value: number;
-  }>;
-  height?: number;
-  className?: string;
-  style?: React.CSSProperties;
-}
-
-interface ITagCloudState {
-  dv: any;
-  height?: number;
-  width: number;
-}
-
-class TagCloud extends Component<ITagCloudProps, ITagCloudState> {
-  state = {
-    dv: null,
-    height: 0,
-    width: 0,
-  };
-  isUnmount!: boolean;
-  requestRef!: number;
-
-  root: HTMLDivElement | undefined;
-  imageMask: HTMLImageElement | undefined;
-
-  componentDidMount() {
-    requestAnimationFrame(() => {
-      this.initTagCloud();
-      this.renderChart(this.props);
-    });
-    window.addEventListener('resize', this.resize, { passive: true });
-  }
-
-  componentDidUpdate(preProps?: ITagCloudProps) {
-    const { data } = this.props;
-    if (preProps && JSON.stringify(preProps.data) !== JSON.stringify(data)) {
-      this.renderChart(this.props);
-    }
-  }
-  componentWillUnmount() {
-    this.isUnmount = true;
-    window.cancelAnimationFrame(this.requestRef);
-    window.removeEventListener('resize', this.resize);
-  }
-  resize = () => {
-    this.requestRef = requestAnimationFrame(() => {
-      this.renderChart(this.props);
-    });
-  };
-  saveRootRef = (node: HTMLDivElement) => {
-    this.root = node;
-  };
-
-  initTagCloud = () => {
-    function getTextAttrs(cfg: {
-      x?: any;
-      y?: any;
-      style?: any;
-      opacity?: any;
-      origin?: any;
-      color?: any;
-    }) {
-      return Object.assign({}, cfg.style, {
-        fillOpacity: cfg.opacity,
-        fontSize: cfg.origin._origin.size,
-        rotate: cfg.origin._origin.rotate,
-        text: cfg.origin._origin.text,
-        textAlign: 'center',
-        fontFamily: cfg.origin._origin.font,
-        fill: cfg.color,
-        textBaseline: 'Alphabetic',
-      });
-    }
-
-    (Shape as any).registerShape('point', 'cloud', {
-      drawShape(
-        cfg: { x: any; y: any },
-        container: { addShape: (arg0: string, arg1: { attrs: any }) => void },
-      ) {
-        const attrs = getTextAttrs(cfg);
-        return container.addShape('text', {
-          attrs: Object.assign(attrs, {
-            x: cfg.x,
-            y: cfg.y,
-          }),
-        });
-      },
-    });
-  };
-
-  @Bind()
-  @Debounce(500)
-  renderChart(nextProps: ITagCloudProps) {
-    // const colors = ['#1890FF', '#41D9C7', '#2FC25B', '#FACC14', '#9AE65C'];
-    const { data, height } = nextProps || this.props;
-
-    if (data.length < 1 || !this.root) {
-      return;
-    }
-
-    const h = height;
-    const w = this.root.offsetWidth;
-
-    const onload = () => {
-      const dv = new DataSet.View().source(data);
-      const range = dv.range('value');
-      const [min, max] = range;
-      dv.transform({
-        type: 'tag-cloud',
-        fields: ['name', 'value'],
-        imageMask: this.imageMask,
-        font: 'Verdana',
-        size: [w, h], // 宽高设置最好根据 imageMask 做调整
-        padding: 0,
-        timeInterval: 5000, // max execute time
-        rotate() {
-          return 0;
-        },
-        fontSize(d: { value: number }) {
-          // eslint-disable-next-line
-          return Math.pow((d.value - min) / (max - min), 2) * (17.5 - 5) + 5;
-        },
-      });
-
-      if (this.isUnmount) {
-        return;
-      }
-
-      this.setState({
-        dv,
-        width: w,
-        height: h,
-      });
-    };
-
-    if (!this.imageMask) {
-      this.imageMask = new Image();
-      this.imageMask.crossOrigin = '';
-      this.imageMask.src = imgUrl;
-
-      this.imageMask.onload = onload;
-    } else {
-      onload();
-    }
-  }
-
-  render() {
-    const { className, height } = this.props;
-    const { dv, width, height: stateHeight } = this.state;
-
-    return (
-      <div
-        className={classNames(styles.tagCloud, className)}
-        style={{ width: '100%', height }}
-        ref={this.saveRootRef}
-      >
-        {dv && (
-          <Chart
-            width={width}
-            height={stateHeight}
-            data={dv}
-            padding={0}
-            scale={{
-              x: { nice: false },
-              y: { nice: false },
-            }}
-          >
-            <Tooltip showTitle={false} />
-            <Coord reflect="y" />
-            <Geom
-              type="point"
-              position="x*y"
-              color="text"
-              shape="cloud"
-              tooltip={[
-                'text*value',
-                function trans(text, value) {
-                  return { name: text, value };
-                },
-              ]}
-            />
-          </Chart>
-        )}
-      </div>
-    );
-  }
-}
-
-export default autoHeight()(TagCloud);

+ 0 - 3
src/pages/analysis/components/Charts/TimelineChart/index.less

@@ -1,3 +0,0 @@
-.timelineChart {
-  background: #fff;
-}

+ 0 - 133
src/pages/analysis/components/Charts/TimelineChart/index.tsx

@@ -1,133 +0,0 @@
-import React from 'react';
-import { Chart, Tooltip, Geom, Legend, Axis } from 'bizcharts';
-import DataSet from '@antv/data-set';
-import Slider from 'bizcharts-plugin-slider';
-import autoHeight from '../autoHeight';
-import styles from './index.less';
-
-export interface ITimelineChartProps {
-  data: Array<{
-    x: number;
-    y1: number;
-    y2: number;
-  }>;
-  title?: string;
-  titleMap: { y1: string; y2: string };
-  padding?: [number, number, number, number];
-  height?: number;
-  style?: React.CSSProperties;
-  borderWidth?: number;
-}
-
-class TimelineChart extends React.Component<ITimelineChartProps> {
-  render() {
-    const {
-      title,
-      height = 400,
-      padding = [60, 20, 40, 40] as [number, number, number, number],
-      titleMap = {
-        y1: 'y1',
-        y2: 'y2',
-      },
-      borderWidth = 2,
-      data: sourceData,
-    } = this.props;
-
-    const data = Array.isArray(sourceData) ? sourceData : [{ x: 0, y1: 0, y2: 0 }];
-
-    data.sort((a, b) => a.x - b.x);
-
-    let max;
-    if (data[0] && data[0].y1 && data[0].y2) {
-      max = Math.max(
-        [...data].sort((a, b) => b.y1 - a.y1)[0].y1,
-        [...data].sort((a, b) => b.y2 - a.y2)[0].y2,
-      );
-    }
-
-    const ds = new DataSet({
-      state: {
-        start: data[0].x,
-        end: data[data.length - 1].x,
-      },
-    });
-
-    const dv = ds.createView();
-    dv.source(data)
-      .transform({
-        type: 'filter',
-        callback: (obj: { x: string }) => {
-          const date = obj.x;
-          return date <= ds.state.end && date >= ds.state.start;
-        },
-      })
-      .transform({
-        type: 'map',
-        callback(row: { y1: string; y2: string }) {
-          const newRow = { ...row };
-          newRow[titleMap.y1] = row.y1;
-          newRow[titleMap.y2] = row.y2;
-          return newRow;
-        },
-      })
-      .transform({
-        type: 'fold',
-        fields: [titleMap.y1, titleMap.y2], // 展开字段集
-        key: 'key', // key字段
-        value: 'value', // value字段
-      });
-
-    const timeScale = {
-      type: 'time',
-      tickInterval: 60 * 60 * 1000,
-      mask: 'HH:mm',
-      range: [0, 1],
-    };
-
-    const cols = {
-      x: timeScale,
-      value: {
-        max,
-        min: 0,
-      },
-    };
-
-    const SliderGen = () => (
-      <Slider
-        padding={[0, padding[1] + 20, 0, padding[3]]}
-        width="auto"
-        height={26}
-        xAxis="x"
-        yAxis="y1"
-        scales={{ x: timeScale }}
-        data={data}
-        start={ds.state.start}
-        end={ds.state.end}
-        backgroundChart={{ type: 'line' }}
-        onChange={({ startValue, endValue }: { startValue: string; endValue: string }) => {
-          ds.setState('start', startValue);
-          ds.setState('end', endValue);
-        }}
-      />
-    );
-
-    return (
-      <div className={styles.timelineChart} style={{ height: height + 30 }}>
-        <div>
-          {title && <h4>{title}</h4>}
-          <Chart height={height} padding={padding} data={dv} scale={cols} forceFit>
-            <Axis name="x" />
-            <Tooltip />
-            <Legend name="key" position="top" />
-            <Geom type="line" position="x*value" size={borderWidth} color="key" />
-          </Chart>
-          <div style={{ marginRight: -20 }}>
-            <SliderGen />
-          </div>
-        </div>
-      </div>
-    );
-  }
-}
-
-export default autoHeight()(TimelineChart);

+ 0 - 28
src/pages/analysis/components/Charts/WaterWave/index.less

@@ -1,28 +0,0 @@
-@import '~antd/lib/style/themes/default.less';
-
-.waterWave {
-  position: relative;
-  display: inline-block;
-  transform-origin: left;
-  .text {
-    position: absolute;
-    top: 32px;
-    left: 0;
-    width: 100%;
-    text-align: center;
-    span {
-      color: @text-color-secondary;
-      font-size: 14px;
-      line-height: 22px;
-    }
-    h4 {
-      color: @heading-color;
-      font-size: 24px;
-      line-height: 32px;
-    }
-  }
-  .waterWaveCanvasWrapper {
-    transform: scale(0.5);
-    transform-origin: 0 0;
-  }
-}

+ 0 - 230
src/pages/analysis/components/Charts/WaterWave/index.tsx

@@ -1,230 +0,0 @@
-import React, { Component } from 'react';
-import autoHeight from '../autoHeight';
-import styles from './index.less';
-
-/* eslint no-return-assign: 0 */
-/* eslint no-mixed-operators: 0 */
-// riddle: https://riddle.alibaba-inc.com/riddles/2d9a4b90
-
-export interface IWaterWaveProps {
-  title: React.ReactNode;
-  color?: string;
-  height?: number;
-  percent: number;
-  style?: React.CSSProperties;
-}
-
-class WaterWave extends Component<IWaterWaveProps> {
-  state = {
-    radio: 1,
-  };
-  timer: number = 0;
-  root: HTMLDivElement | undefined | null;
-  node: HTMLCanvasElement | undefined | null;
-
-  componentDidMount() {
-    this.renderChart();
-    this.resize();
-    window.addEventListener(
-      'resize',
-      () => {
-        requestAnimationFrame(() => this.resize());
-      },
-      { passive: true },
-    );
-  }
-
-  componentDidUpdate(props: IWaterWaveProps) {
-    const { percent } = this.props;
-    if (props.percent !== percent) {
-      // 不加这个会造成绘制缓慢
-      this.renderChart('update');
-    }
-  }
-
-  componentWillUnmount() {
-    cancelAnimationFrame(this.timer);
-    if (this.node) {
-      this.node.innerHTML = '';
-    }
-    window.removeEventListener('resize', this.resize);
-  }
-
-  resize = () => {
-    if (this.root) {
-      const { height = 1 } = this.props;
-      const { offsetWidth } = this.root.parentNode as HTMLElement;
-      this.setState({
-        radio: offsetWidth < height ? offsetWidth / height : 1,
-      });
-    }
-  };
-  renderChart(type?: string) {
-    const { percent, color = '#1890FF' } = this.props;
-    const data = percent / 100;
-    const self = this;
-    cancelAnimationFrame(this.timer);
-
-    if (!this.node || (data !== 0 && !data)) {
-      return;
-    }
-
-    const canvas = this.node;
-    const ctx = canvas.getContext('2d');
-    if (!ctx) {
-      return;
-    }
-    const canvasWidth = canvas.width;
-    const canvasHeight = canvas.height;
-    const radius = canvasWidth / 2;
-    const lineWidth = 2;
-    const cR = radius - lineWidth;
-
-    ctx.beginPath();
-    ctx.lineWidth = lineWidth * 2;
-
-    const axisLength = canvasWidth - lineWidth;
-    const unit = axisLength / 8;
-    const range = 0.2; // 振幅
-    let currRange = range;
-    const xOffset = lineWidth;
-    let sp = 0; // 周期偏移量
-    let currData = 0;
-    const waveupsp = 0.005; // 水波上涨速度
-
-    let arcStack: number[][] = [];
-    const bR = radius - lineWidth;
-    const circleOffset = -(Math.PI / 2);
-    let circleLock = true;
-
-    for (let i = circleOffset; i < circleOffset + 2 * Math.PI; i += 1 / (8 * Math.PI)) {
-      arcStack.push([radius + bR * Math.cos(i), radius + bR * Math.sin(i)]);
-    }
-
-    const cStartPoint = arcStack.shift() as number[];
-    ctx.strokeStyle = color;
-    ctx.moveTo(cStartPoint[0], cStartPoint[1]);
-
-    function drawSin() {
-      if (!ctx) {
-        return;
-      }
-      ctx.beginPath();
-      ctx.save();
-
-      const sinStack = [];
-      for (let i = xOffset; i <= xOffset + axisLength; i += 20 / axisLength) {
-        const x = sp + (xOffset + i) / unit;
-        const y = Math.sin(x) * currRange;
-        const dx = i;
-        const dy = 2 * cR * (1 - currData) + (radius - cR) - unit * y;
-
-        ctx.lineTo(dx, dy);
-        sinStack.push([dx, dy]);
-      }
-
-      const startPoint = sinStack.shift() as number[];
-
-      ctx.lineTo(xOffset + axisLength, canvasHeight);
-      ctx.lineTo(xOffset, canvasHeight);
-      ctx.lineTo(startPoint[0], startPoint[1]);
-
-      const gradient = ctx.createLinearGradient(0, 0, 0, canvasHeight);
-      gradient.addColorStop(0, '#ffffff');
-      gradient.addColorStop(1, color);
-      ctx.fillStyle = gradient;
-      ctx.fill();
-      ctx.restore();
-    }
-
-    function render() {
-      if (!ctx) {
-        return;
-      }
-      ctx.clearRect(0, 0, canvasWidth, canvasHeight);
-      if (circleLock && type !== 'update') {
-        if (arcStack.length) {
-          const temp = arcStack.shift() as number[];
-          ctx.lineTo(temp[0], temp[1]);
-          ctx.stroke();
-        } else {
-          circleLock = false;
-          ctx.lineTo(cStartPoint[0], cStartPoint[1]);
-          ctx.stroke();
-          arcStack = [];
-
-          ctx.globalCompositeOperation = 'destination-over';
-          ctx.beginPath();
-          ctx.lineWidth = lineWidth;
-          ctx.arc(radius, radius, bR, 0, 2 * Math.PI, true);
-
-          ctx.beginPath();
-          ctx.save();
-          ctx.arc(radius, radius, radius - 3 * lineWidth, 0, 2 * Math.PI, true);
-
-          ctx.restore();
-          ctx.clip();
-          ctx.fillStyle = color;
-        }
-      } else {
-        if (data >= 0.85) {
-          if (currRange > range / 4) {
-            const t = range * 0.01;
-            currRange -= t;
-          }
-        } else if (data <= 0.1) {
-          if (currRange < range * 1.5) {
-            const t = range * 0.01;
-            currRange += t;
-          }
-        } else {
-          if (currRange <= range) {
-            const t = range * 0.01;
-            currRange += t;
-          }
-          if (currRange >= range) {
-            const t = range * 0.01;
-            currRange -= t;
-          }
-        }
-        if (data - currData > 0) {
-          currData += waveupsp;
-        }
-        if (data - currData < 0) {
-          currData -= waveupsp;
-        }
-
-        sp += 0.07;
-        drawSin();
-      }
-      self.timer = requestAnimationFrame(render);
-    }
-    render();
-  }
-  render() {
-    const { radio } = this.state;
-    const { percent, title, height = 1 } = this.props;
-    return (
-      <div
-        className={styles.waterWave}
-        ref={n => (this.root = n)}
-        style={{ transform: `scale(${radio})` }}
-      >
-        <div style={{ width: height, height, overflow: 'hidden' }}>
-          <canvas
-            className={styles.waterWaveCanvasWrapper}
-            ref={n => (this.node = n)}
-            width={height * 2}
-            height={height * 2}
-          />
-        </div>
-        <div className={styles.text} style={{ width: height }}>
-          {title && <span>{title}</span>}
-          <h4>{percent}%</h4>
-        </div>
-      </div>
-    );
-  }
-}
-
-export default autoHeight()(WaterWave);

+ 0 - 75
src/pages/analysis/components/Charts/autoHeight.tsx

@@ -1,75 +0,0 @@
-import React from 'react';
-
-export type IReactComponent<P = any> =
-  | React.StatelessComponent<P>
-  | React.ComponentClass<P>
-  | React.ClassicComponentClass<P>;
-
-function computeHeight(node: HTMLDivElement) {
-  node.style.height = '100%';
-  const totalHeight = parseInt(getComputedStyle(node).height + '', 10);
-  const padding =
-    parseInt(getComputedStyle(node).paddingTop + '', 10) +
-    parseInt(getComputedStyle(node).paddingBottom + '', 10);
-  return totalHeight - padding;
-}
-
-function getAutoHeight(n: HTMLDivElement) {
-  if (!n) {
-    return 0;
-  }
-
-  const node = n;
-
-  let height = computeHeight(node);
-  const parentNode = node.parentNode as HTMLDivElement;
-  if (parentNode) {
-    height = computeHeight(parentNode);
-  }
-
-  return height;
-}
-
-interface IAutoHeightProps {
-  height?: number;
-}
-
-function autoHeight() {
-  return function<P extends IAutoHeightProps>(
-    WrappedComponent: React.ComponentClass<P> | React.SFC<P>,
-  ): React.ComponentClass<P> {
-    class AutoHeightComponent extends React.Component<P & IAutoHeightProps> {
-      state = {
-        computedHeight: 0,
-      };
-      root!: HTMLDivElement;
-      componentDidMount() {
-        const { height } = this.props;
-        if (!height) {
-          let h = getAutoHeight(this.root);
-          // eslint-disable-next-line
-          this.setState({ computedHeight: h });
-          if (h < 1) {
-            h = getAutoHeight(this.root);
-            this.setState({ computedHeight: h });
-          }
-        }
-      }
-      handleRoot = (node: HTMLDivElement) => {
-        this.root = node;
-      };
-      render() {
-        const { height } = this.props;
-        const { computedHeight } = this.state;
-        const h = height || computedHeight;
-        return (
-          <div ref={this.handleRoot}>
-            {h > 0 && <WrappedComponent {...this.props} height={h} />}
-          </div>
-        );
-      }
-    }
-    return AutoHeightComponent;
-  };
-}
-export default autoHeight;

+ 0 - 3
src/pages/analysis/components/Charts/bizcharts.d.ts

@@ -1,3 +0,0 @@
-import * as BizChart from 'bizcharts';
-
-export = BizChart;

+ 0 - 3
src/pages/analysis/components/Charts/bizcharts.tsx

@@ -1,3 +0,0 @@
-import * as BizChart from 'bizcharts';
-
-export default BizChart;

+ 0 - 19
src/pages/analysis/components/Charts/index.less

@@ -1,19 +0,0 @@
-.miniChart {
-  position: relative;
-  width: 100%;
-  .chartContent {
-    position: absolute;
-    bottom: -28px;
-    width: 100%;
-    > div {
-      margin: 0 -5px;
-      overflow: hidden;
-    }
-  }
-  .chartLoading {
-    position: absolute;
-    top: 16px;
-    left: 50%;
-    margin-left: -7px;
-  }
-}

+ 0 - 45
src/pages/analysis/components/Charts/index.tsx

@@ -1,45 +0,0 @@
-import numeral from 'numeral';
-import ChartCard from './ChartCard';
-import Field from './Field';
-import Bar from './Bar';
-import Pie from './Pie';
-import Gauge from './Gauge';
-import MiniArea from './MiniArea';
-import MiniBar from './MiniBar';
-import MiniProgress from './MiniProgress';
-import WaterWave from './WaterWave';
-import TagCloud from './TagCloud';
-import TimelineChart from './TimelineChart';
-
-const yuan = (val: number | string) => `¥ ${numeral(val).format('0,0')}`;
-
-const Charts = {
-  yuan,
-  Bar,
-  Pie,
-  Gauge,
-  MiniBar,
-  MiniArea,
-  MiniProgress,
-  ChartCard,
-  Field,
-  WaterWave,
-  TagCloud,
-  TimelineChart,
-};
-
-export {
-  Charts as default,
-  yuan,
-  Bar,
-  Pie,
-  Gauge,
-  MiniBar,
-  MiniArea,
-  MiniProgress,
-  ChartCard,
-  Field,
-  WaterWave,
-  TagCloud,
-  TimelineChart,
-};

+ 0 - 162
src/pages/analysis/components/IntroduceRow.tsx

@@ -1,162 +0,0 @@
-import React from 'react';
-import { Row, Col, Icon, Tooltip } from 'antd';
-import { FormattedMessage } from 'umi-plugin-react/locale';
-import Charts from './Charts';
-import numeral from 'numeral';
-import styles from '../style.less';
-import Yuan from '../utils/Yuan';
-import Trend from './Trend';
-import { IVisitData } from '../data.d';
-const { ChartCard, MiniArea, MiniBar, MiniProgress, Field } = Charts;
-
-const topColResponsiveProps = {
-  xs: 24,
-  sm: 12,
-  md: 12,
-  lg: 12,
-  xl: 6,
-  style: { marginBottom: 24 },
-};
-
-const IntroduceRow = ({ loading, visitData }: { loading: boolean; visitData: IVisitData[] }) => {
-  return (
-    <Row gutter={24}>
-      <Col {...topColResponsiveProps}>
-        <ChartCard
-          bordered={false}
-          title={
-            <FormattedMessage id="analysis.analysis.total-sales" defaultMessage="Total Sales" />
-          }
-          action={
-            <Tooltip
-              title={
-                <FormattedMessage id="analysis.analysis.introduce" defaultMessage="Introduce" />
-              }
-            >
-              <Icon type="info-circle-o" />
-            </Tooltip>
-          }
-          loading={loading}
-          total={() => <Yuan>126560</Yuan>}
-          footer={
-            <Field
-              label={
-                <FormattedMessage id="analysis.analysis.day-sales" defaultMessage="Daily Sales" />
-              }
-              value={`¥${numeral(12423).format('0,0')}`}
-            />
-          }
-          contentHeight={46}
-        >
-          <Trend flag="up" style={{ marginRight: 16 }}>
-            <FormattedMessage id="analysis.analysis.week" defaultMessage="Weekly Changes" />
-            <span className={styles.trendText}>12%</span>
-          </Trend>
-          <Trend flag="down">
-            <FormattedMessage id="analysis.analysis.day" defaultMessage="Daily Changes" />
-            <span className={styles.trendText}>11%</span>
-          </Trend>
-        </ChartCard>
-      </Col>
-
-      <Col {...topColResponsiveProps}>
-        <ChartCard
-          bordered={false}
-          loading={loading}
-          title={<FormattedMessage id="analysis.analysis.visits" defaultMessage="Visits" />}
-          action={
-            <Tooltip
-              title={
-                <FormattedMessage id="analysis.analysis.introduce" defaultMessage="Introduce" />
-              }
-            >
-              <Icon type="info-circle-o" />
-            </Tooltip>
-          }
-          total={numeral(8846).format('0,0')}
-          footer={
-            <Field
-              label={
-                <FormattedMessage id="analysis.analysis.day-visits" defaultMessage="Daily Visits" />
-              }
-              value={numeral(1234).format('0,0')}
-            />
-          }
-          contentHeight={46}
-        >
-          <MiniArea color="#975FE4" data={visitData} />
-        </ChartCard>
-      </Col>
-      <Col {...topColResponsiveProps}>
-        <ChartCard
-          bordered={false}
-          loading={loading}
-          title={<FormattedMessage id="analysis.analysis.payments" defaultMessage="Payments" />}
-          action={
-            <Tooltip
-              title={
-                <FormattedMessage id="analysis.analysis.introduce" defaultMessage="Introduce" />
-              }
-            >
-              <Icon type="info-circle-o" />
-            </Tooltip>
-          }
-          total={numeral(6560).format('0,0')}
-          footer={
-            <Field
-              label={
-                <FormattedMessage
-                  id="analysis.analysis.conversion-rate"
-                  defaultMessage="Conversion Rate"
-                />
-              }
-              value="60%"
-            />
-          }
-          contentHeight={46}
-        >
-          <MiniBar data={visitData} />
-        </ChartCard>
-      </Col>
-      <Col {...topColResponsiveProps}>
-        <ChartCard
-          loading={loading}
-          bordered={false}
-          title={
-            <FormattedMessage
-              id="analysis.analysis.operational-effect"
-              defaultMessage="Operational Effect"
-            />
-          }
-          action={
-            <Tooltip
-              title={
-                <FormattedMessage id="analysis.analysis.introduce" defaultMessage="Introduce" />
-              }
-            >
-              <Icon type="info-circle-o" />
-            </Tooltip>
-          }
-          total="78%"
-          footer={
-            <div style={{ whiteSpace: 'nowrap', overflow: 'hidden' }}>
-              <Trend flag="up" style={{ marginRight: 16 }}>
-                <FormattedMessage id="analysis.analysis.week" defaultMessage="Weekly Changes" />
-                <span className={styles.trendText}>12%</span>
-              </Trend>
-              <Trend flag="down">
-                <FormattedMessage id="analysis.analysis.day" defaultMessage="Weekly Changes" />
-                <span className={styles.trendText}>11%</span>
-              </Trend>
-            </div>
-          }
-          contentHeight={46}
-        >
-          <MiniProgress percent={78} strokeWidth={8} target={80} color="#13C2C2" />
-        </ChartCard>
-      </Col>
-    </Row>
-  );
-};
-
-export default IntroduceRow;

+ 0 - 68
src/pages/analysis/components/NumberInfo/index.less

@@ -1,68 +0,0 @@
-@import '~antd/lib/style/themes/default.less';
-
-.numberInfo {
-  .suffix {
-    margin-left: 4px;
-    color: @text-color;
-    font-size: 16px;
-    font-style: normal;
-  }
-  .numberInfoTitle {
-    margin-bottom: 16px;
-    color: @text-color;
-    font-size: @font-size-lg;
-    transition: all 0.3s;
-  }
-  .numberInfoSubTitle {
-    height: 22px;
-    overflow: hidden;
-    color: @text-color-secondary;
-    font-size: @font-size-base;
-    line-height: 22px;
-    white-space: nowrap;
-    text-overflow: ellipsis;
-    word-break: break-all;
-  }
-  .numberInfoValue {
-    margin-top: 4px;
-    overflow: hidden;
-    font-size: 0;
-    white-space: nowrap;
-    text-overflow: ellipsis;
-    word-break: break-all;
-    & > span {
-      display: inline-block;
-      height: 32px;
-      margin-right: 32px;
-      color: @heading-color;
-      font-size: 24px;
-      line-height: 32px;
-    }
-    .subTotal {
-      margin-right: 0;
-      color: @text-color-secondary;
-      font-size: @font-size-lg;
-      vertical-align: top;
-      i {
-        margin-left: 4px;
-        font-size: 12px;
-        transform: scale(0.82);
-      }
-      :global {
-        .anticon-caret-up {
-          color: @red-6;
-        }
-        .anticon-caret-down {
-          color: @green-6;
-        }
-      }
-    }
-  }
-}
-.numberInfolight {
-  .numberInfoValue {
-    & > span {
-      color: @text-color;
-    }
-  }
-}

+ 0 - 61
src/pages/analysis/components/NumberInfo/index.tsx

@@ -1,61 +0,0 @@
-import React from 'react';
-import { Icon } from 'antd';
-import classNames from 'classnames';
-import styles from './index.less';
-export interface NumberInfoProps {
-  title?: React.ReactNode | string;
-  subTitle?: React.ReactNode | string;
-  total?: React.ReactNode | string;
-  status?: 'up' | 'down';
-  theme?: string;
-  gap?: number;
-  subTotal?: number;
-  suffix?: string;
-  style?: React.CSSProperties;
-}
-const NumberInfo: React.SFC<NumberInfoProps> = ({
-  theme,
-  title,
-  subTitle,
-  total,
-  subTotal,
-  status,
-  suffix,
-  gap,
-  ...rest
-}) => (
-  <div
-    className={classNames(styles.numberInfo, {
-      [styles[`numberInfo${theme}`]]: theme,
-    })}
-    {...rest}
-  >
-    {title && (
-      <div className={styles.numberInfoTitle} title={typeof title === 'string' ? title : ''}>
-        {title}
-      </div>
-    )}
-    {subTitle && (
-      <div
-        className={styles.numberInfoSubTitle}
-        title={typeof subTitle === 'string' ? subTitle : ''}
-      >
-        {subTitle}
-      </div>
-    )}
-    <div className={styles.numberInfoValue} style={gap ? { marginTop: gap } : {}}>
-      <span>
-        {total}
-        {suffix && <em className={styles.suffix}>{suffix}</em>}
-      </span>
-      {(status || subTotal) && (
-        <span className={styles.subTotal}>
-          {subTotal}
-          {status && <Icon type={`caret-${status}`} />}
-        </span>
-      )}
-    </div>
-  </div>
-);
-
-export default NumberInfo;

+ 0 - 82
src/pages/analysis/components/OfflineData.tsx

@@ -1,82 +0,0 @@
-import React from 'react';
-import { Card, Tabs, Row, Col } from 'antd';
-import { formatMessage, FormattedMessage } from 'umi-plugin-react/locale';
-import Charts from './Charts';
-import styles from '../style.less';
-import NumberInfo from './NumberInfo';
-import { IOfflineData, IOfflineChartData } from '../data';
-const { TimelineChart, Pie } = Charts;
-
-const CustomTab = ({
-  data,
-  currentTabKey: currentKey,
-}: {
-  data: IOfflineData;
-  currentTabKey: string;
-}) => {
-  return (
-    <Row gutter={8} style={{ width: 138, margin: '8px 0' }}>
-      <Col span={12}>
-        <NumberInfo
-          title={data.name}
-          subTitle={
-            <FormattedMessage
-              id="analysis.analysis.conversion-rate"
-              defaultMessage="Conversion Rate"
-            />
-          }
-          gap={2}
-          total={`${data.cvr * 100}%`}
-          theme={currentKey !== data.name ? 'light' : undefined}
-        />
-      </Col>
-      <Col span={12} style={{ paddingTop: 36 }}>
-        <Pie
-          animate={false}
-          inner={0.55}
-          tooltip={false}
-          margin={[0, 0, 0, 0]}
-          percent={data.cvr * 100}
-          height={64}
-        />
-      </Col>
-    </Row>
-  );
-};
-
-const { TabPane } = Tabs;
-
-const OfflineData = ({
-  activeKey,
-  loading,
-  offlineData,
-  offlineChartData,
-  handleTabChange,
-}: {
-  activeKey: string;
-  loading: boolean;
-  offlineData: IOfflineData[];
-  offlineChartData: IOfflineChartData[];
-  handleTabChange: (activeKey: string) => void;
-}) => (
-  <Card loading={loading} className={styles.offlineCard} bordered={false} style={{ marginTop: 32 }}>
-    <Tabs activeKey={activeKey} onChange={handleTabChange}>
-      {offlineData.map(shop => (
-        <TabPane tab={<CustomTab data={shop} currentTabKey={activeKey} />} key={shop.name}>
-          <div style={{ padding: '0 24px' }}>
-            <TimelineChart
-              height={400}
-              data={offlineChartData}
-              titleMap={{
-                y1: formatMessage({ id: 'analysis.analysis.traffic' }),
-                y2: formatMessage({ id: 'analysis.analysis.payments' }),
-              }}
-            />
-          </div>
-        </TabPane>
-      ))}
-    </Tabs>
-  </Card>
-);
-
-export default OfflineData;

+ 0 - 10
src/pages/analysis/components/PageLoading/index.tsx

@@ -1,10 +0,0 @@
-import React from 'react';
-import { Spin } from 'antd';
-
-// loading components from code split
-// https://umijs.org/plugin/umi-plugin-react.html#dynamicimport
-export default () => (
-  <div style={{ paddingTop: 100, textAlign: 'center' }}>
-    <Spin size="large" />
-  </div>
-);

+ 0 - 79
src/pages/analysis/components/ProportionSales.tsx

@@ -1,79 +0,0 @@
-import React from 'react';
-import { Card, Radio } from 'antd';
-import Charts from './Charts';
-import { FormattedMessage } from 'umi-plugin-react/locale';
-import styles from '../style.less';
-import Yuan from '../utils/Yuan';
-import { RadioChangeEvent } from 'antd/lib/radio';
-import { ISalesData } from '../data';
-
-const { Pie } = Charts;
-
-const ProportionSales = ({
-  dropdownGroup,
-  salesType,
-  loading,
-  salesPieData,
-  handleChangeSalesType,
-}: {
-  loading: boolean;
-  dropdownGroup: React.ReactNode;
-  salesType: 'all' | 'online' | 'stores';
-  salesPieData: ISalesData[];
-  handleChangeSalesType?: (e: RadioChangeEvent) => void;
-}) => {
-  return (
-    <Card
-      loading={loading}
-      className={styles.salesCard}
-      bordered={false}
-      title={
-        <FormattedMessage
-          id="analysis.analysis.the-proportion-of-sales"
-          defaultMessage="The Proportion of Sales"
-        />
-      }
-      bodyStyle={{ padding: 24 }}
-      extra={
-        <div className={styles.salesCardExtra}>
-          {dropdownGroup}
-          <div className={styles.salesTypeRadio}>
-            <Radio.Group value={salesType} onChange={handleChangeSalesType}>
-              <Radio.Button value="all">
-                <FormattedMessage id="analysis.channel.all" defaultMessage="ALL" />
-              </Radio.Button>
-              <Radio.Button value="online">
-                <FormattedMessage id="analysis.channel.online" defaultMessage="Online" />
-              </Radio.Button>
-              <Radio.Button value="stores">
-                <FormattedMessage id="analysis.channel.stores" defaultMessage="Stores" />
-              </Radio.Button>
-            </Radio.Group>
-          </div>
-        </div>
-      }
-      style={{ marginTop: 24 }}
-    >
-      <div
-        style={{
-          minHeight: 380,
-        }}
-      >
-        <h4 style={{ marginTop: 8, marginBottom: 32 }}>
-          <FormattedMessage id="analysis.analysis.sales" defaultMessage="Sales" />
-        </h4>
-        <Pie
-          hasLegend
-          subTitle={<FormattedMessage id="analysis.analysis.sales" defaultMessage="Sales" />}
-          total={() => <Yuan>{salesPieData.reduce((pre, now) => now.y + pre, 0)}</Yuan>}
-          data={salesPieData}
-          valueFormat={value => <Yuan>{value}</Yuan>}
-          height={248}
-          lineWidth={4}
-        />
-      </div>
-    </Card>
-  );
-};
-
-export default ProportionSales;

+ 0 - 162
src/pages/analysis/components/SalesCard.tsx

@@ -1,162 +0,0 @@
-import React from 'react';
-import { Row, Col, Card, Tabs, DatePicker } from 'antd';
-import { FormattedMessage, formatMessage } from 'umi-plugin-react/locale';
-import numeral from 'numeral';
-import Charts from './Charts';
-import { RangePickerValue } from 'antd/lib/date-picker/interface';
-import { ISalesData } from '../data';
-import styles from '../style.less';
-
-const { Bar } = Charts;
-
-const { RangePicker } = DatePicker;
-const { TabPane } = Tabs;
-
-const rankingListData: { title: string; total: number }[] = [];
-for (let i = 0; i < 7; i += 1) {
-  rankingListData.push({
-    title: formatMessage({ id: 'analysis.analysis.test' }, { no: i }),
-    total: 323234,
-  });
-}
-
-const SalesCard = ({
-  rangePickerValue,
-  salesData,
-  isActive,
-  handleRangePickerChange,
-  loading,
-  selectDate,
-}: {
-  rangePickerValue: RangePickerValue;
-  isActive: (key: 'today' | 'week' | 'month' | 'year') => string;
-  salesData: ISalesData[];
-  loading: boolean;
-  handleRangePickerChange: (dates: RangePickerValue, dateStrings: [string, string]) => void;
-  selectDate: (key: 'today' | 'week' | 'month' | 'year') => void;
-}) => (
-  <Card loading={loading} bordered={false} bodyStyle={{ padding: 0 }}>
-    <div className={styles.salesCard}>
-      <Tabs
-        tabBarExtraContent={
-          <div className={styles.salesExtraWrap}>
-            <div className={styles.salesExtra}>
-              <a className={isActive('today')} onClick={() => selectDate('today')}>
-                <FormattedMessage id="analysis.analysis.all-day" defaultMessage="All Day" />
-              </a>
-              <a className={isActive('week')} onClick={() => selectDate('week')}>
-                <FormattedMessage id="analysis.analysis.all-week" defaultMessage="All Week" />
-              </a>
-              <a className={isActive('month')} onClick={() => selectDate('month')}>
-                <FormattedMessage id="analysis.analysis.all-month" defaultMessage="All Month" />
-              </a>
-              <a className={isActive('year')} onClick={() => selectDate('year')}>
-                <FormattedMessage id="analysis.analysis.all-year" defaultMessage="All Year" />
-              </a>
-            </div>
-            <RangePicker
-              value={rangePickerValue}
-              onChange={handleRangePickerChange}
-              style={{ width: 256 }}
-            />
-          </div>
-        }
-        size="large"
-        tabBarStyle={{ marginBottom: 24 }}
-      >
-        <TabPane
-          tab={<FormattedMessage id="analysis.analysis.sales" defaultMessage="Sales" />}
-          key="sales"
-        >
-          <Row>
-            <Col xl={16} lg={12} md={12} sm={24} xs={24}>
-              <div className={styles.salesBar}>
-                <Bar
-                  height={295}
-                  title={
-                    <FormattedMessage
-                      id="analysis.analysis.sales-trend"
-                      defaultMessage="Sales Trend"
-                    />
-                  }
-                  data={salesData}
-                />
-              </div>
-            </Col>
-            <Col xl={8} lg={12} md={12} sm={24} xs={24}>
-              <div className={styles.salesRank}>
-                <h4 className={styles.rankingTitle}>
-                  <FormattedMessage
-                    id="analysis.analysis.sales-ranking"
-                    defaultMessage="Sales Ranking"
-                  />
-                </h4>
-                <ul className={styles.rankingList}>
-                  {rankingListData.map((item, i) => (
-                    <li key={item.title}>
-                      <span className={`${styles.rankingItemNumber} ${i < 3 ? styles.active : ''}`}>
-                        {i + 1}
-                      </span>
-                      <span className={styles.rankingItemTitle} title={item.title}>
-                        {item.title}
-                      </span>
-                      <span className={styles.rankingItemValue}>
-                        {numeral(item.total).format('0,0')}
-                      </span>
-                    </li>
-                  ))}
-                </ul>
-              </div>
-            </Col>
-          </Row>
-        </TabPane>
-        <TabPane
-          tab={<FormattedMessage id="analysis.analysis.visits" defaultMessage="Visits" />}
-          key="views"
-        >
-          <Row>
-            <Col xl={16} lg={12} md={12} sm={24} xs={24}>
-              <div className={styles.salesBar}>
-                <Bar
-                  height={292}
-                  title={
-                    <FormattedMessage
-                      id="analysis.analysis.visits-trend"
-                      defaultMessage="Visits Trend"
-                    />
-                  }
-                  data={salesData}
-                />
-              </div>
-            </Col>
-            <Col xl={8} lg={12} md={12} sm={24} xs={24}>
-              <div className={styles.salesRank}>
-                <h4 className={styles.rankingTitle}>
-                  <FormattedMessage
-                    id="analysis.analysis.visits-ranking"
-                    defaultMessage="Visits Ranking"
-                  />
-                </h4>
-                <ul className={styles.rankingList}>
-                  {rankingListData.map((item, i) => (
-                    <li key={item.title}>
-                      <span className={`${styles.rankingItemNumber} ${i < 3 ? styles.active : ''}`}>
-                        {i + 1}
-                      </span>
-                      <span className={styles.rankingItemTitle} title={item.title}>
-                        {item.title}
-                      </span>
-                      <span>{numeral(item.total).format('0,0')}</span>
-                    </li>
-                  ))}
-                </ul>
-              </div>
-            </Col>
-          </Row>
-        </TabPane>
-      </Tabs>
-    </div>
-  </Card>
-);
-
-export default SalesCard;

+ 0 - 128
src/pages/analysis/components/TopSearch.tsx

@@ -1,128 +0,0 @@
-import React from 'react';
-import { Row, Col, Table, Tooltip, Card, Icon } from 'antd';
-import { FormattedMessage } from 'umi-plugin-react/locale';
-import Charts from './Charts';
-import Trend from './Trend';
-import NumberInfo from './NumberInfo';
-import numeral from 'numeral';
-import styles from '../style.less';
-import { ISearchData, IVisitData2 } from '../data';
-
-const { MiniArea } = Charts;
-
-const columns = [
-  {
-    title: <FormattedMessage id="analysis.table.rank" defaultMessage="Rank" />,
-    dataIndex: 'index',
-    key: 'index',
-  },
-  {
-    title: <FormattedMessage id="analysis.table.search-keyword" defaultMessage="Search keyword" />,
-    dataIndex: 'keyword',
-    key: 'keyword',
-    render: (text: React.ReactNode) => <a href="/">{text}</a>,
-  },
-  {
-    title: <FormattedMessage id="analysis.table.users" defaultMessage="Users" />,
-    dataIndex: 'count',
-    key: 'count',
-    sorter: (a: { count: number }, b: { count: number }) => a.count - b.count,
-    className: styles.alignRight,
-  },
-  {
-    title: <FormattedMessage id="analysis.table.weekly-range" defaultMessage="Weekly Range" />,
-    dataIndex: 'range',
-    key: 'range',
-    sorter: (a: { range: number }, b: { range: number }) => a.range - b.range,
-    render: (text: React.ReactNode, record: { status: number }) => (
-      <Trend flag={record.status === 1 ? 'down' : 'up'}>
-        <span style={{ marginRight: 4 }}>{text}%</span>
-      </Trend>
-    ),
-  },
-];
-
-const TopSearch = ({
-  loading,
-  visitData2,
-  searchData,
-  dropdownGroup,
-}: {
-  loading: boolean;
-  visitData2: IVisitData2[];
-  dropdownGroup: React.ReactNode;
-  searchData: ISearchData[];
-}) => (
-  <Card
-    loading={loading}
-    bordered={false}
-    title={
-      <FormattedMessage
-        id="analysis.analysis.online-top-search"
-        defaultMessage="Online Top Search"
-      />
-    }
-    extra={dropdownGroup}
-    style={{ marginTop: 24 }}
-  >
-    <Row gutter={68}>
-      <Col sm={12} xs={24} style={{ marginBottom: 24 }}>
-        <NumberInfo
-          subTitle={
-            <span>
-              <FormattedMessage id="analysis.analysis.search-users" defaultMessage="search users" />
-              <Tooltip
-                title={
-                  <FormattedMessage id="analysis.analysis.introduce" defaultMessage="introduce" />
-                }
-              >
-                <Icon style={{ marginLeft: 8 }} type="info-circle-o" />
-              </Tooltip>
-            </span>
-          }
-          gap={8}
-          total={numeral(12321).format('0,0')}
-          status="up"
-          subTotal={17.1}
-        />
-        <MiniArea line height={45} data={visitData2} />
-      </Col>
-      <Col sm={12} xs={24} style={{ marginBottom: 24 }}>
-        <NumberInfo
-          subTitle={
-            <span>
-              <FormattedMessage
-                id="analysis.analysis.per-capita-search"
-                defaultMessage="Per Capita Search"
-              />
-              <Tooltip
-                title={
-                  <FormattedMessage id="analysis.analysis.introduce" defaultMessage="introduce" />
-                }
-              >
-                <Icon style={{ marginLeft: 8 }} type="info-circle-o" />
-              </Tooltip>
-            </span>
-          }
-          total={2.7}
-          status="down"
-          subTotal={26.2}
-          gap={8}
-        />
-        <MiniArea line height={45} data={visitData2} />
-      </Col>
-    </Row>
-    <Table<any>
-      rowKey={record => record.index}
-      size="small"
-      columns={columns}
-      dataSource={searchData}
-      pagination={{
-        style: { marginBottom: 0 },
-        pageSize: 5,
-      }}
-    />
-  </Card>
-);
-
-export default TopSearch;

+ 0 - 37
src/pages/analysis/components/Trend/index.less

@@ -1,37 +0,0 @@
-@import '~antd/lib/style/themes/default.less';
-
-.trendItem {
-  display: inline-block;
-  font-size: @font-size-base;
-  line-height: 22px;
-
-  .up,
-  .down {
-    position: relative;
-    top: 1px;
-    margin-left: 4px;
-    i {
-      font-size: 12px;
-      transform: scale(0.83);
-    }
-  }
-  .up {
-    color: @red-6;
-  }
-  .down {
-    top: -1px;
-    color: @green-6;
-  }
-
-  &.trendItemGrey .up,
-  &.trendItemGrey .down {
-    color: @text-color;
-  }
-
-  &.reverseColor .up {
-    color: @green-6;
-  }
-  &.reverseColor .down {
-    color: @red-6;
-  }
-}

+ 0 - 42
src/pages/analysis/components/Trend/index.tsx

@@ -1,42 +0,0 @@
-import React from 'react';
-import { Icon } from 'antd';
-import classNames from 'classnames';
-import styles from './index.less';
-
-export interface ITrendProps {
-  colorful?: boolean;
-  flag: 'up' | 'down';
-  style?: React.CSSProperties;
-  reverseColor?: boolean;
-  className?: string;
-}
-
-const Trend: React.SFC<ITrendProps> = ({
-  colorful = true,
-  reverseColor = false,
-  flag,
-  children,
-  className,
-  ...rest
-}) => {
-  const classString = classNames(
-    styles.trendItem,
-    {
-      [styles.trendItemGrey]: !colorful,
-      [styles.reverseColor]: reverseColor && colorful,
-    },
-    className,
-  );
-  return (
-    <div {...rest} className={classString} title={typeof children === 'string' ? children : ''}>
-      <span>{children}</span>
-      {flag && (
-        <span className={styles[flag]}>
-          <Icon type={`caret-${flag}`} />
-        </span>
-      )}
-    </div>
-  );
-};
-
-export default Trend;

+ 0 - 67
src/pages/analysis/data.d.ts

@@ -1,67 +0,0 @@
-export interface IVisitData {
-  x: string;
-  y: number;
-}
-
-export interface IVisitData2 {
-  x: string;
-  y: number;
-}
-
-export interface ISalesData {
-  x: string;
-  y: number;
-}
-
-export interface ISearchData {
-  index: number;
-  keyword: string;
-  count: number;
-  range: number;
-  status: number;
-}
-
-export interface IOfflineData {
-  name: string;
-  cvr: number;
-}
-
-export interface IOfflineChartData {
-  x: any;
-  y1: number;
-  y2: number;
-}
-
-export interface ISalesTypeData {
-  x: string;
-  y: number;
-}
-
-export interface ISalesTypeDataOnline {
-  x: string;
-  y: number;
-}
-
-export interface ISalesTypeDataOffline {
-  x: string;
-  y: number;
-}
-
-export interface IRadarData {
-  name: string;
-  label: string;
-  value: number;
-}
-
-export interface IAnalysisData {
-  visitData: IVisitData[];
-  visitData2: IVisitData2[];
-  salesData: ISalesData[];
-  searchData: ISearchData[];
-  offlineData: IOfflineData[];
-  offlineChartData: IOfflineChartData[];
-  salesTypeData: ISalesTypeData[];
-  salesTypeDataOnline: ISalesTypeDataOnline[];
-  salesTypeDataOffline: ISalesTypeDataOffline[];
-  radarData: IRadarData[];
-}

+ 0 - 215
src/pages/analysis/index.tsx

@@ -1,215 +0,0 @@
-import React, { Component, Suspense } from 'react';
-import { connect } from 'dva';
-import { Row, Col, Icon, Menu, Dropdown } from 'antd';
-import { RangePickerValue } from 'antd/lib/date-picker/interface';
-import { getTimeDistance } from './utils/utils';
-import styles from './style.less';
-import PageLoading from './components/PageLoading';
-import { Dispatch } from 'redux';
-import { IAnalysisData } from './data.d';
-import { RadioChangeEvent } from 'antd/lib/radio';
-import { GridContent } from '@ant-design/pro-layout';
-
-const IntroduceRow = React.lazy(() => import('./components/IntroduceRow'));
-const SalesCard = React.lazy(() => import('./components/SalesCard'));
-const TopSearch = React.lazy(() => import('./components/TopSearch'));
-const ProportionSales = React.lazy(() => import('./components/ProportionSales'));
-const OfflineData = React.lazy(() => import('./components/OfflineData'));
-
-interface AnalysisProps {
-  analysis: IAnalysisData;
-  dispatch: Dispatch<any>;
-  loading: boolean;
-}
-
-interface AnalysisState {
-  salesType: 'all' | 'online' | 'stores';
-  currentTabKey: string;
-  rangePickerValue: RangePickerValue;
-}
-
-@connect(
-  ({
-    analysis,
-    loading,
-  }: {
-    analysis: any;
-    loading: {
-      effects: { [key: string]: boolean };
-    };
-  }) => ({
-    analysis,
-    loading: loading.effects['analysis/fetch'],
-  }),
-)
-class Analysis extends Component<AnalysisProps, AnalysisState> {
-  state: AnalysisState = {
-    salesType: 'all',
-    currentTabKey: '',
-    rangePickerValue: getTimeDistance('year'),
-  };
-  reqRef!: number;
-  timeoutId!: number;
-  componentDidMount() {
-    const { dispatch } = this.props;
-    this.reqRef = requestAnimationFrame(() => {
-      dispatch({
-        type: 'analysis/fetch',
-      });
-    });
-    setTimeout(() => {
-      this.setState({
-        loading: false,
-      });
-    }, 2000);
-  }
-
-  componentWillUnmount() {
-    const { dispatch } = this.props;
-    dispatch({
-      type: 'analysis/clear',
-    });
-    cancelAnimationFrame(this.reqRef);
-    clearTimeout(this.timeoutId);
-  }
-
-  handleChangeSalesType = (e: RadioChangeEvent) => {
-    this.setState({
-      salesType: e.target.value,
-    });
-  };
-
-  handleTabChange = (key: string) => {
-    this.setState({
-      currentTabKey: key,
-    });
-  };
-
-  handleRangePickerChange = (rangePickerValue: RangePickerValue) => {
-    const { dispatch } = this.props;
-    this.setState({
-      rangePickerValue,
-    });
-
-    dispatch({
-      type: 'analysis/fetchSalesData',
-    });
-  };
-
-  selectDate = (type: 'today' | 'week' | 'month' | 'year') => {
-    const { dispatch } = this.props;
-    this.setState({
-      rangePickerValue: getTimeDistance(type),
-    });
-
-    dispatch({
-      type: 'analysis/fetchSalesData',
-    });
-  };
-
-  isActive = (type: 'today' | 'week' | 'month' | 'year') => {
-    const { rangePickerValue } = this.state;
-    const value = getTimeDistance(type);
-    if (!rangePickerValue[0] || !rangePickerValue[1]) {
-      return '';
-    }
-    if (
-      rangePickerValue[0].isSame(value[0], 'day') &&
-      rangePickerValue[1].isSame(value[1], 'day')
-    ) {
-      return styles.currentDate;
-    }
-    return '';
-  };
-
-  render() {
-    const { rangePickerValue, salesType, currentTabKey } = this.state;
-    const { analysis, loading } = this.props;
-    const {
-      visitData,
-      visitData2,
-      salesData,
-      searchData,
-      offlineData,
-      offlineChartData,
-      salesTypeData,
-      salesTypeDataOnline,
-      salesTypeDataOffline,
-    } = analysis;
-    let salesPieData;
-    if (salesType === 'all') {
-      salesPieData = salesTypeData;
-    } else {
-      salesPieData = salesType === 'online' ? salesTypeDataOnline : salesTypeDataOffline;
-    }
-    const menu = (
-      <Menu>
-        <Menu.Item>操作一</Menu.Item>
-        <Menu.Item>操作二</Menu.Item>
-      </Menu>
-    );
-
-    const dropdownGroup = (
-      <span className={styles.iconGroup}>
-        <Dropdown overlay={menu} placement="bottomRight">
-          <Icon type="ellipsis" />
-        </Dropdown>
-      </span>
-    );
-
-    const activeKey = currentTabKey || (offlineData[0] && offlineData[0].name);
-    return (
-      <GridContent>
-        <React.Fragment>
-          <Suspense fallback={<PageLoading />}>
-            <IntroduceRow loading={loading} visitData={visitData} />
-          </Suspense>
-          <Suspense fallback={null}>
-            <SalesCard
-              rangePickerValue={rangePickerValue}
-              salesData={salesData}
-              isActive={this.isActive}
-              handleRangePickerChange={this.handleRangePickerChange}
-              loading={loading}
-              selectDate={this.selectDate}
-            />
-          </Suspense>
-          <Row gutter={24}>
-            <Col xl={12} lg={24} md={24} sm={24} xs={24}>
-              <Suspense fallback={null}>
-                <TopSearch
-                  loading={loading}
-                  visitData2={visitData2}
-                  searchData={searchData}
-                  dropdownGroup={dropdownGroup}
-                />
-              </Suspense>
-            </Col>
-            <Col xl={12} lg={24} md={24} sm={24} xs={24}>
-              <Suspense fallback={null}>
-                <ProportionSales
-                  dropdownGroup={dropdownGroup}
-                  salesType={salesType}
-                  loading={loading}
-                  salesPieData={salesPieData}
-                  handleChangeSalesType={this.handleChangeSalesType}
-                />
-              </Suspense>
-            </Col>
-          </Row>
-          <Suspense fallback={null}>
-            <OfflineData
-              activeKey={activeKey}
-              loading={loading}
-              offlineData={offlineData}
-              offlineChartData={offlineChartData}
-              handleTabChange={this.handleTabChange}
-            />
-          </Suspense>
-        </React.Fragment>
-      </GridContent>
-    );
-  }
-}
-
-export default Analysis;

+ 0 - 34
src/pages/analysis/locales/en-US.ts

@@ -1,34 +0,0 @@
-export default {
-  'analysis.analysis.test': 'Gongzhuan No.{no} shop',
-  'analysis.analysis.introduce': 'Introduce',
-  'analysis.analysis.total-sales': 'Total Sales',
-  'analysis.analysis.day-sales': 'Daily Sales',
-  'analysis.analysis.visits': 'Visits',
-  'analysis.analysis.visits-trend': 'Visits Trend',
-  'analysis.analysis.visits-ranking': 'Visits Ranking',
-  'analysis.analysis.day-visits': 'Daily Visits',
-  'analysis.analysis.week': 'WoW Change',
-  'analysis.analysis.day': 'DoD Change',
-  'analysis.analysis.payments': 'Payments',
-  'analysis.analysis.conversion-rate': 'Conversion Rate',
-  'analysis.analysis.operational-effect': 'Operational Effect',
-  'analysis.analysis.sales-trend': 'Stores Sales Trend',
-  'analysis.analysis.sales-ranking': 'Sales Ranking',
-  'analysis.analysis.all-year': 'All Year',
-  'analysis.analysis.all-month': 'All Month',
-  'analysis.analysis.all-week': 'All Week',
-  'analysis.analysis.all-day': 'All day',
-  'analysis.analysis.search-users': 'Search Users',
-  'analysis.analysis.per-capita-search': 'Per Capita Search',
-  'analysis.analysis.online-top-search': 'Online Top Search',
-  'analysis.analysis.the-proportion-of-sales': 'The Proportion Of Sales',
-  'analysis.channel.all': 'ALL',
-  'analysis.channel.online': 'Online',
-  'analysis.channel.stores': 'Stores',
-  'analysis.analysis.sales': 'Sales',
-  'analysis.analysis.traffic': 'Traffic',
-  'analysis.table.rank': 'Rank',
-  'analysis.table.search-keyword': 'Keyword',
-  'analysis.table.users': 'Users',
-  'analysis.table.weekly-range': 'Weekly Range',
-};

+ 0 - 34
src/pages/analysis/locales/pt-BR.ts

@@ -1,34 +0,0 @@
-export default {
-  'analysis.analysis.test': 'Gongzhuan No.{no} shop',
-  'analysis.analysis.introduce': 'Introduzir',
-  'analysis.analysis.total-sales': 'Vendas Totais',
-  'analysis.analysis.day-sales': 'Vendas do Dia',
-  'analysis.analysis.visits': 'Visitas',
-  'analysis.analysis.visits-trend': 'Tendência de Visitas',
-  'analysis.analysis.visits-ranking': 'Ranking de Visitas',
-  'analysis.analysis.day-visits': 'Visitas do Dia',
-  'analysis.analysis.week': 'Taxa Semanal',
-  'analysis.analysis.day': 'Taxa Diária',
-  'analysis.analysis.payments': 'Pagamentos',
-  'analysis.analysis.conversion-rate': 'Taxa de Conversão',
-  'analysis.analysis.operational-effect': 'Efeito Operacional',
-  'analysis.analysis.sales-trend': 'Tendência de Vendas das Lojas',
-  'analysis.analysis.sales-ranking': 'Ranking de Vendas',
-  'analysis.$2': 'Todo ano',
-  'analysis.analysis.all-month': 'Todo mês',
-  'analysis.analysis.all-week': 'Toda semana',
-  'analysis.analysis.all-day': 'Todo dia',
-  'analysis.analysis.search-users': 'Pesquisa de Usuários',
-  'analysis.analysis.per-capita-search': 'Busca Per Capta',
-  'analysis.analysis.online-top-search': 'Mais Buscadas Online',
-  'analysis.analysis.the-proportion-of-sales': 'The Proportion Of Sales',
-  'analysis.channel.all': 'Tudo',
-  'analysis.channel.online': 'Online',
-  'analysis.channel.stores': 'Lojas',
-  'analysis.analysis.sales': 'Vendas',
-  'analysis.analysis.traffic': 'Tráfego',
-  'analysis.table.rank': 'Rank',
-  'analysis.table.search-keyword': 'Palavra chave',
-  'analysis.table.users': 'Usuários',
-  'analysis.table.weekly-range': 'Faixa Semanal',
-};

+ 0 - 34
src/pages/analysis/locales/zh-CN.ts

@@ -1,34 +0,0 @@
-export default {
-  'analysis.analysis.test': '工专路 {no} 号店',
-  'analysis.analysis.introduce': '指标说明',
-  'analysis.analysis.total-sales': '总销售额',
-  'analysis.analysis.day-sales': '日销售额',
-  'analysis.analysis.visits': '访问量',
-  'analysis.analysis.visits-trend': '访问量趋势',
-  'analysis.analysis.visits-ranking': '门店访问量排名',
-  'analysis.analysis.day-visits': '日访问量',
-  'analysis.analysis.week': '周同比',
-  'analysis.analysis.day': '日同比',
-  'analysis.analysis.payments': '支付笔数',
-  'analysis.analysis.conversion-rate': '转化率',
-  'analysis.analysis.operational-effect': '运营活动效果',
-  'analysis.analysis.sales-trend': '销售趋势',
-  'analysis.analysis.sales-ranking': '门店销售额排名',
-  'analysis.analysis.all-year': '全年',
-  'analysis.analysis.all-month': '本月',
-  'analysis.analysis.all-week': '本周',
-  'analysis.analysis.all-day': '今日',
-  'analysis.analysis.search-users': '搜索用户数',
-  'analysis.analysis.per-capita-search': '人均搜索次数',
-  'analysis.analysis.online-top-search': '线上热门搜索',
-  'analysis.analysis.the-proportion-of-sales': '销售额类别占比',
-  'analysis.channel.all': '全部渠道',
-  'analysis.channel.online': '线上',
-  'analysis.channel.stores': '门店',
-  'analysis.analysis.sales': '销售额',
-  'analysis.analysis.traffic': '客流量',
-  'analysis.table.rank': '排名',
-  'analysis.table.search-keyword': '搜索关键词',
-  'analysis.table.users': '用户数',
-  'analysis.table.weekly-range': '周涨幅',
-};

+ 0 - 34
src/pages/analysis/locales/zh-TW.ts

@@ -1,34 +0,0 @@
-export default {
-  'analysis.analysis.test': '工專路 {no} 號店',
-  'analysis.analysis.introduce': '指標說明',
-  'analysis.analysis.total-sales': '總銷售額',
-  'analysis.analysis.day-sales': '日銷售額',
-  'analysis.analysis.visits': '訪問量',
-  'analysis.analysis.visits-trend': '訪問量趨勢',
-  'analysis.analysis.visits-ranking': '門店訪問量排名',
-  'analysis.analysis.day-visits': '日訪問量',
-  'analysis.analysis.week': '周同比',
-  'analysis.analysis.day': '日同比',
-  'analysis.analysis.payments': '支付筆數',
-  'analysis.analysis.conversion-rate': '轉化率',
-  'analysis.analysis.operational-effect': '運營活動效果',
-  'analysis.analysis.sales-trend': '銷售趨勢',
-  'analysis.analysis.sales-ranking': '門店銷售額排名',
-  'analysis.analysis.all-year': '全年',
-  'analysis.analysis.all-month': '本月',
-  'analysis.analysis.all-week': '本周',
-  'analysis.analysis.all-day': '今日',
-  'analysis.analysis.search-users': '搜索用戶數',
-  'analysis.analysis.per-capita-search': '人均搜索次數',
-  'analysis.analysis.online-top-search': '線上熱門搜索',
-  'analysis.analysis.the-proportion-of-sales': '銷售額類別占比',
-  'analysis.channel.all': '全部渠道',
-  'analysis.channel.online': '線上',
-  'analysis.channel.stores': '門店',
-  'analysis.analysis.sales': '銷售額',
-  'analysis.analysis.traffic': '客流量',
-  'analysis.table.rank': '排名',
-  'analysis.table.search-keyword': '搜索關鍵詞',
-  'analysis.table.users': '用戶數',
-  'analysis.table.weekly-range': '周漲幅',
-};

+ 0 - 84
src/pages/analysis/model.tsx

@@ -1,84 +0,0 @@
-import { fakeChartData } from './service';
-import { IAnalysisData } from './data';
-import { Reducer } from 'redux';
-import { EffectsCommandMap } from 'dva';
-import { AnyAction } from 'redux';
-
-export type Effect = (
-  action: AnyAction,
-  effects: EffectsCommandMap & { select: <T>(func: (state: IAnalysisData) => T) => T },
-) => void;
-
-export interface ModelType {
-  namespace: string;
-  state: IAnalysisData;
-  effects: {
-    fetch: Effect;
-    fetchSalesData: Effect;
-  };
-  reducers: {
-    save: Reducer<IAnalysisData>;
-    clear: Reducer<IAnalysisData>;
-  };
-}
-
-const Model: ModelType = {
-  namespace: 'analysis',
-
-  state: {
-    visitData: [],
-    visitData2: [],
-    salesData: [],
-    searchData: [],
-    offlineData: [],
-    offlineChartData: [],
-    salesTypeData: [],
-    salesTypeDataOnline: [],
-    salesTypeDataOffline: [],
-    radarData: [],
-  },
-
-  effects: {
-    *fetch(_, { call, put }) {
-      const response = yield call(fakeChartData);
-      yield put({
-        type: 'save',
-        payload: response,
-      });
-    },
-    *fetchSalesData(_, { call, put }) {
-      const response = yield call(fakeChartData);
-      yield put({
-        type: 'save',
-        payload: {
-          salesData: response.salesData,
-        },
-      });
-    },
-  },
-
-  reducers: {
-    save(state, { payload }) {
-      return {
-        ...state,
-        ...payload,
-      };
-    },
-    clear() {
-      return {
-        visitData: [],
-        visitData2: [],
-        salesData: [],
-        searchData: [],
-        offlineData: [],
-        offlineChartData: [],
-        salesTypeData: [],
-        salesTypeDataOnline: [],
-        salesTypeDataOffline: [],
-        radarData: [],
-      };
-    },
-  },
-};
-
-export default Model;

+ 0 - 5
src/pages/analysis/service.tsx

@@ -1,5 +0,0 @@
-import request from 'umi-request';
-
-export async function fakeChartData() {
-  return request('/api/analysis/fake_chart_data');
-}

+ 0 - 185
src/pages/analysis/style.less

@@ -1,185 +0,0 @@
-@import '~antd/lib/style/themes/default.less';
-@import './utils/utils.less';
-
-.iconGroup {
-  i {
-    margin-left: 16px;
-    color: @text-color-secondary;
-    cursor: pointer;
-    transition: color 0.32s;
-    &:hover {
-      color: @text-color;
-    }
-  }
-}
-
-.rankingList {
-  margin: 25px 0 0;
-  padding: 0;
-  list-style: none;
-  li {
-    .clearfix();
-
-    display: flex;
-    align-items: center;
-    margin-top: 16px;
-    span {
-      color: @text-color;
-      font-size: 14px;
-      line-height: 22px;
-    }
-    .rankingItemNumber {
-      display: inline-block;
-      width: 20px;
-      height: 20px;
-      margin-top: 1.5px;
-      margin-right: 16px;
-      font-weight: 600;
-      font-size: 12px;
-      line-height: 20px;
-      text-align: center;
-      background-color: @background-color-base;
-      border-radius: 20px;
-      &.active {
-        color: #fff;
-        background-color: #314659;
-      }
-    }
-    .rankingItemTitle {
-      flex: 1;
-      margin-right: 8px;
-      overflow: hidden;
-      white-space: nowrap;
-      text-overflow: ellipsis;
-    }
-  }
-}
-
-.salesExtra {
-  display: inline-block;
-  margin-right: 24px;
-  a {
-    margin-left: 24px;
-    color: @text-color;
-    &:hover {
-      color: @primary-color;
-    }
-    &.currentDate {
-      color: @primary-color;
-    }
-  }
-}
-
-.salesCard {
-  .salesBar {
-    padding: 0 0 32px 32px;
-  }
-  .salesRank {
-    padding: 0 32px 32px 72px;
-  }
-  :global {
-    .ant-tabs-bar {
-      padding-left: 16px;
-      .ant-tabs-nav .ant-tabs-tab {
-        padding-top: 16px;
-        padding-bottom: 14px;
-        line-height: 24px;
-      }
-    }
-    .ant-tabs-extra-content {
-      padding-right: 24px;
-      line-height: 55px;
-    }
-    .ant-card-head {
-      position: relative;
-    }
-    .ant-card-head-title {
-      align-items: normal;
-    }
-  }
-}
-
-.salesCardExtra {
-  height: inherit;
-}
-
-.salesTypeRadio {
-  position: absolute;
-  right: 54px;
-  bottom: 12px;
-}
-
-.offlineCard {
-  :global {
-    .ant-tabs-ink-bar {
-      bottom: auto;
-    }
-    .ant-tabs-bar {
-      border-bottom: none;
-    }
-    .ant-tabs-nav-container-scrolling {
-      padding-right: 40px;
-      padding-left: 40px;
-    }
-    .ant-tabs-tab-prev-icon::before {
-      position: relative;
-      left: 6px;
-    }
-    .ant-tabs-tab-next-icon::before {
-      position: relative;
-      right: 6px;
-    }
-    .ant-tabs-tab-active h4 {
-      color: @primary-color;
-    }
-  }
-}
-
-.twoColLayout {
-  .salesCard {
-    height: calc(100% - 24px);
-  }
-}
-
-.trendText {
-  margin-left: 8px;
-  color: @heading-color;
-}
-
-@media screen and (max-width: @screen-lg) {
-  .salesExtra {
-    display: none;
-  }
-
-  .rankingList {
-    li {
-      span:first-child {
-        margin-right: 8px;
-      }
-    }
-  }
-}
-
-@media screen and (max-width: @screen-md) {
-  .rankingTitle {
-    margin-top: 16px;
-  }
-
-  .salesCard .salesBar {
-    padding: 16px;
-  }
-}
-
-@media screen and (max-width: @screen-sm) {
-  .salesExtraWrap {
-    display: none;
-  }
-
-  .salesCard {
-    :global {
-      .ant-tabs-content {
-        padding-top: 30px;
-      }
-    }
-  }
-}

+ 0 - 33
src/pages/analysis/utils/Yuan.tsx

@@ -1,33 +0,0 @@
-import React from 'react';
-import { yuan } from '../components/Charts';
-/**
- * 减少使用 dangerouslySetInnerHTML
- */
-export default class Yuan extends React.Component<{
-  children: React.ReactText;
-}> {
-  main: HTMLSpanElement | undefined | null;
-  componentDidMount() {
-    this.renderToHtml();
-  }
-
-  componentDidUpdate() {
-    this.renderToHtml();
-  }
-  renderToHtml = () => {
-    const { children } = this.props;
-    if (this.main) {
-      this.main.innerHTML = yuan(children);
-    }
-  };
-
-  render() {
-    return (
-      <span
-        ref={ref => {
-          this.main = ref;
-        }}
-      />
-    );
-  }
-}

+ 0 - 50
src/pages/analysis/utils/utils.less

@@ -1,50 +0,0 @@
-.textOverflow() {
-  overflow: hidden;
-  white-space: nowrap;
-  text-overflow: ellipsis;
-  word-break: break-all;
-}
-
-.textOverflowMulti(@line: 3, @bg: #fff) {
-  position: relative;
-  max-height: @line * 1.5em;
-  margin-right: -1em;
-  padding-right: 1em;
-  overflow: hidden;
-  line-height: 1.5em;
-  text-align: justify;
-  &::before {
-    position: absolute;
-    right: 14px;
-    bottom: 0;
-    padding: 0 1px;
-    background: @bg;
-    content: '...';
-  }
-  &::after {
-    position: absolute;
-    right: 14px;
-    width: 1em;
-    height: 1em;
-    margin-top: 0.2em;
-    background: white;
-    content: '';
-  }
-}
-
-// mixins for clearfix
-// ------------------------
-.clearfix() {
-  zoom: 1;
-  &::before,
-  &::after {
-    display: table;
-    content: ' ';
-  }
-  &::after {
-    clear: both;
-    height: 0;
-    font-size: 0;
-    visibility: hidden;
-  }
-}

+ 0 - 53
src/pages/analysis/utils/utils.ts

@@ -1,53 +0,0 @@
-import moment from 'moment';
-import { RangePickerValue } from 'antd/lib/date-picker/interface';
-
-export function fixedZero(val: number) {
-  return val * 1 < 10 ? `0${val}` : val;
-}
-
-export function getTimeDistance(type: 'today' | 'week' | 'month' | 'year'): RangePickerValue {
-  const now = new Date();
-  const oneDay = 1000 * 60 * 60 * 24;
-
-  if (type === 'today') {
-    now.setHours(0);
-    now.setMinutes(0);
-    now.setSeconds(0);
-    return [moment(now), moment(now.getTime() + (oneDay - 1000))];
-  }
-
-  if (type === 'week') {
-    let day = now.getDay();
-    now.setHours(0);
-    now.setMinutes(0);
-    now.setSeconds(0);
-
-    if (day === 0) {
-      day = 6;
-    } else {
-      day -= 1;
-    }
-
-    const beginTime = now.getTime() - day * oneDay;
-
-    return [moment(beginTime), moment(beginTime + (7 * oneDay - 1000))];
-  }
-
-  if (type === 'month') {
-    const year = now.getFullYear();
-    const month = now.getMonth();
-    const nextDate = moment(now).add(1, 'months');
-    const nextYear = nextDate.year();
-    const nextMonth = nextDate.month();
-
-    return [
-      moment(`${year}-${fixedZero(month + 1)}-01 00:00:00`),
-      moment(moment(`${nextYear}-${fixedZero(nextMonth + 1)}-01 00:00:00`).valueOf() - 1000),
-    ];
-  }
-
-  return [
-    moment(`${now.getFullYear()}-01-01 00:00:00`),
-    moment(`${now.getFullYear()}-12-31 23:59:59`),
-  ];
-}