Parcourir la source

Merge branch 'dev' of http://git.ycjcjy.com/zhiyuxing/estateagents-admin-manager into dev

# Conflicts:
#	config/routes.js
#	src/services/apis.js
魏超 il y a 5 ans
Parent
révision
395f951118

+ 12
- 1
config/routes.js Voir le fichier

@@ -560,7 +560,18 @@ export default [
560 560
               {
561 561
                 path: '/statistical/activity/index',
562 562
                 name: '活动统计',
563
-                component: './statistical/activity/index',
563
+                component: './statistical/activity/index'
564
+              },
565
+              {
566
+                path: '/statistical/building/detail',
567
+                name: '项目统计详情',
568
+                component: './statistical/building/detail',
569
+                hideInMenu: true,
570
+              },
571
+              {
572
+                path: '/statistical/consultant/index',
573
+                name: '置业顾问KPI',
574
+                component: './statistical/consultant/index',
564 575
               },
565 576
             ],
566 577
           },

+ 1
- 0
src/components/SelectButton/BuildSelect.jsx Voir le fichier

@@ -55,6 +55,7 @@ const BuildingSelect = props => {
55 55
       filterOption={(input, option) =>
56 56
         option.props.children && option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
57 57
       }>
58
+          <Option key="" value="">全部项目</Option>
58 59
           {data.map(building => (
59 60
             <Option key={building.buildingId} value={building.buildingId}>{building.buildingName}</Option>
60 61
           ))}

+ 61
- 0
src/pages/statistical/building/component/StatsChart.jsx Voir le fichier

@@ -0,0 +1,61 @@
1
+import React, { Component, useState, useEffect } from 'react';
2
+import { Form, Icon, Input, Button, DatePicker, Select, Card, Row, Col, Pagination, Alert, Table, Avatar, Radio, Modal, Descriptions } from 'antd';
3
+import moment from 'moment';
4
+import echarts from 'echarts/lib/echarts';
5
+import EChart from '../../../../components/EchartsTest/EChart';
6
+import router from 'umi/router';
7
+
8
+class StatsChart extends React.Component {
9
+
10
+  constructor(props) {
11
+    super(props)
12
+    this.state = {}
13
+  }
14
+
15
+  render() {
16
+    const { data = {}} = this.props
17
+    const options = {
18
+      title: {
19
+        text: this.props.title,
20
+        subtext: this.props.subtext,
21
+    },
22
+    xAxis: {
23
+        type: 'category',
24
+        axisLabel: {rotate: 45},
25
+        data: data.buildingNameList || []
26
+    },
27
+    tooltip: {},
28
+    yAxis: {
29
+        type: 'value'
30
+    },
31
+    series: {
32
+      type: 'bar',
33
+      name: this.props.title,
34
+      barWidth: 50,
35
+      data: data.numList || [],
36
+      itemStyle: {
37
+        normal: {
38
+          barBorderRadius: [50, 50, 0, 0],
39
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
40
+            offset: 0,
41
+            color: '#FD8A95'
42
+          }, {
43
+            offset: 1,
44
+            color: '#F13043'
45
+          }]),
46
+          shadowColor: 'rgba(0, 0, 0, 0.4)',
47
+
48
+        }
49
+      }
50
+    }
51
+}
52
+
53
+    return (
54
+    <>
55
+      <EChart options={options} style={{ width: '100%', height: '400px', }} />
56
+    </>
57
+    )
58
+  }
59
+}
60
+
61
+export default StatsChart

+ 84
- 0
src/pages/statistical/building/component/StatsChartLine.jsx Voir le fichier

@@ -0,0 +1,84 @@
1
+import React, { Component, useState, useEffect } from 'react';
2
+import { Form, Icon, Input, Button, DatePicker, Select, Card, Row, Col, Pagination, Alert, Table, Avatar, Radio, Modal, Descriptions } from 'antd';
3
+import moment from 'moment';
4
+import echarts from 'echarts/lib/echarts';
5
+import EChart from '../../../../components/EchartsTest/EChart';
6
+import router from 'umi/router';
7
+
8
+class StatsChart extends React.Component {
9
+
10
+  constructor(props) {
11
+    super(props)
12
+    this.state = {}
13
+  }
14
+
15
+  render() {
16
+    const { data = {}} = this.props
17
+    const options = {
18
+      title: {
19
+          text: this.props.title,
20
+      },
21
+      tooltip: {
22
+          trigger: 'axis'
23
+      },
24
+      legend: {
25
+          data: ['公客数', '私客数', '新增客户数', '访问人数']
26
+      },
27
+      grid: {
28
+          left: '3%',
29
+          right: '4%',
30
+          bottom: '3%',
31
+          containLabel: true
32
+      },
33
+      toolbox: {
34
+          feature: {
35
+              saveAsImage: {}
36
+          }
37
+      },
38
+      xAxis: {
39
+          type: 'category',
40
+          boundaryGap: false,
41
+          axisLabel: {rotate: 45},
42
+          data: data.timeList || []
43
+      },
44
+      yAxis: {
45
+          type: 'value'
46
+      },
47
+      series: [
48
+          {
49
+              name: '公客数',
50
+              type: 'line',
51
+              stack: '总量',
52
+              data: data.gkList || []
53
+          },
54
+          {
55
+              name: '私客数',
56
+              type: 'line',
57
+              stack: '总量',
58
+              data: data.skList || []
59
+          },
60
+          {
61
+              name: '新增客户数',
62
+              type: 'line',
63
+              stack: '总量',
64
+              data: data.khList || []
65
+          },
66
+          {
67
+              name: '访问人数',
68
+              type: 'line',
69
+              stack: '总量',
70
+              data: data.uvList || []
71
+          }
72
+      ]
73
+  };
74
+  
75
+
76
+    return (
77
+    <>
78
+      <EChart options={options} style={{ width: '100%', height: '400px', }} />
79
+    </>
80
+    )
81
+  }
82
+}
83
+
84
+export default StatsChart

+ 180
- 0
src/pages/statistical/building/detail.jsx Voir le fichier

@@ -0,0 +1,180 @@
1
+import React, { Component, useState, useEffect } from 'react';
2
+import { Form, Icon, Input, Button, DatePicker, Select, Card, Row, Col, Pagination, Alert, Table, Avatar, Radio, Modal, Descriptions } from 'antd';
3
+import moment from 'moment';
4
+import EChart from '../../../components/EchartsTest/EChart';
5
+import request from '../../../utils/request';
6
+import apis from '../../../services/apis';
7
+import StatsChartLine from './component/StatsChartLine';
8
+import BuildSelect from '../../../components/SelectButton/BuildSelect'
9
+import router from 'umi/router';
10
+
11
+
12
+const { RangePicker } = DatePicker;
13
+const { Option } = Select
14
+
15
+let daterange = []
16
+let tableTitle = ['类型']
17
+
18
+class buildingDetailStats extends React.Component {
19
+
20
+  constructor(props) {
21
+    super(props)
22
+    this.state = {
23
+      barData: {},
24
+      tableData: [],
25
+      total: 0,
26
+      userType: 'all',
27
+      endDate: {},
28
+      startDate: {},
29
+      buildingId: props.location.query.buildingId,
30
+      buildingName: props.location.query.buildingName,
31
+    }
32
+  }
33
+
34
+  componentDidMount() {
35
+    this.getTimeBarDate(moment().subtract(7, 'day').toDate(),new Date())
36
+    this.getTimeTableData(moment().subtract(7, 'day').toDate(),new Date())
37
+    this.setState({...this.state, endDate: new Date(), startDate: moment().subtract(7, 'day').toDate() })
38
+    
39
+  }
40
+
41
+  // 获取图表数据
42
+  getTimeBarDate = (startDate, endDate) => {
43
+    request({ ...apis.stats.timeBarList, params: { startDate, endDate, buildingId: this.state.buildingId } }).then((data) => {
44
+        this.setState({...this.state, barData: data})
45
+      })
46
+  }
47
+
48
+  //获取表格数据
49
+  getTimeTableData = (startDate, endDate,pageNum,pageSize,sortField,sortOrder) => {
50
+    request({ ...apis.stats.timeTableList, params: { startDate, endDate, buildingId: this.state.buildingId,pageNum,pageSize,sortField,sortOrder } }).then((data) => {
51
+        this.setState({...this.state, tableData: data.records, total: data.total})
52
+      })
53
+  }
54
+
55
+  formatDate = (start, end) => {
56
+    const tempStartDate = `${moment(start).format('YYYY-MM-DDT00:00:00.000')}Z`
57
+    const tempEndDate = `${moment(end).format('YYYY-MM-DDT23:59:59.999')}Z`
58
+    return { startDate: tempStartDate, endDate: tempEndDate }
59
+  }
60
+
61
+  //时间选择器改变的时候
62
+  onChangetime = (_dates, dateStrings) => {
63
+    daterange[0] = `${moment(dateStrings[0]).format('YYYY-MM-DDT00:00:00.000')}Z`
64
+    daterange[1] = `${moment(dateStrings[1]).format('YYYY-MM-DDT23:59:59.999')}Z`
65
+  }
66
+
67
+  //切换三个标签页
68
+  getDataOf = (days) => {
69
+    this.getTimeBarDate(moment().subtract(days, 'day').toDate(),new Date())
70
+    this.getTimeTableData(moment().subtract(days, 'day').toDate(),new Date())
71
+    this.setState({ ...this.state, endDate: new Date(), startDate: moment().subtract(days, 'day').toDate() })
72
+  }
73
+
74
+  //点击查询
75
+  datalist = () => {
76
+    this.getTimeBarDate(daterange[0] === undefined ? moment().subtract(7, 'day').toDate() : daterange[0],daterange[1] === undefined ? new Date() : daterange[1])
77
+    this.getTimeTableData(daterange[0] === undefined ? moment().subtract(7, 'day').toDate() : daterange[0],daterange[1] === undefined ? new Date() : daterange[1])
78
+    this.setState({ 
79
+      ...this.state,
80
+      endDate: daterange[1] === undefined ? new Date() : daterange[1],
81
+      startDate: daterange[0] === undefined ? moment().subtract(7, 'day').toDate() : daterange[0],
82
+    })
83
+    
84
+  }
85
+
86
+  //排序
87
+  handleTableChange = (pagination, filters, sorter) => {
88
+    console.log(pagination, filters, sorter)
89
+    this.getTimeTableData(this.state.startDate,this.state.endDate,pagination.current,10,sorter.columnKey,sorter.order)
90
+  };
91
+
92
+  //导出
93
+  exportBuildingStats = () => {
94
+    request({ ...apis.stats.buildingTimeExport, params: { startDate: this.state.startDate, endDate: this.state.endDate, buildingId: this.state.buildingId } })
95
+      .then(data => {
96
+        if (!data) {
97
+          return
98
+        }
99
+        const url = window.URL.createObjectURL(new Blob([data]))
100
+        const link = document.createElement('a')
101
+        link.style.display = 'none'
102
+        link.href = url
103
+        link.setAttribute('download', '项目详情统计.xlsx')
104
+        document.body.append(link)
105
+        link.click()
106
+      }).catch(() => {
107
+
108
+      })
109
+  }
110
+
111
+  render() {
112
+    const columns = [
113
+        {
114
+          title: '日期',
115
+          dataIndex: 'createDate',
116
+          key: 'createDate',
117
+        },
118
+        {
119
+          title: '新增客户',
120
+          dataIndex: 'khNum',
121
+          key: 'kh_num',
122
+          sorter: true,
123
+        },
124
+        {
125
+          title: '公客',
126
+          dataIndex: 'gkNum',
127
+          key: 'gk_num',
128
+          sorter: true,
129
+        },
130
+        {
131
+          title: '私客',
132
+          dataIndex: 'skNum',
133
+          key: 'sk_num',
134
+          sorter: true,
135
+        },
136
+        {
137
+            title: '访问人数',
138
+            dataIndex: 'uvNum',
139
+            key: 'uv_num',
140
+            sorter: true,
141
+        },
142
+      ];
143
+
144
+    return (
145
+    <div>
146
+      <Radio.Group buttonStyle="solid" defaultValue="a">
147
+          <Radio.Button value="c" onClick={() => this.getDataOf(0)}>今日</Radio.Button>
148
+          <Radio.Button value="a" onClick={() => this.getDataOf(7)}>最近7天</Radio.Button>
149
+          <Radio.Button value="b" onClick={() => this.getDataOf(30)}>最近1月</Radio.Button>
150
+        </Radio.Group>
151
+        <RangePicker
152
+          style={{ paddingLeft: '30px' }}
153
+          ranges={{
154
+            Today: [moment(), moment()],
155
+            'This Month': [moment().startOf('month'), moment().endOf('month')],
156
+          }}
157
+          onChange={(_dates, dateStrings) => this.onChangetime(_dates, dateStrings)}
158
+        />
159
+        <Button type="primary" htmlType="submit" style={{ marginLeft: '30px' }} onClick={() => this.datalist()}>
160
+          查询
161
+        </Button>
162
+        <Button type="danger" onClick={() => router.go(-1)} style={{ marginBottom: '18px', marginLeft: '30px' }}>重置</Button>
163
+
164
+        <StatsChartLine title={this.state.buildingName} data={this.state.barData} />
165
+        <Row>
166
+            <Col span={22}>
167
+              <span>详细数据</span>
168
+            </Col>
169
+            <Col span={2}>
170
+              <Button type="primary" onClick={this.exportBuildingStats}>导出</Button>
171
+            </Col>
172
+        </Row>
173
+        
174
+        <Table style={{marginTop:'20px'}} dataSource={this.state.tableData} columns={columns} pagination={{ total: this.state.total}} onChange={this.handleTableChange} scroll={{ y: 500 }}></Table>
175
+    </div>
176
+    )
177
+  }
178
+}
179
+
180
+export default buildingDetailStats

+ 153
- 119
src/pages/statistical/building/index.jsx Voir le fichier

@@ -4,73 +4,51 @@ import moment from 'moment';
4 4
 import EChart from '../../../components/EchartsTest/EChart';
5 5
 import request from '../../../utils/request';
6 6
 import apis from '../../../services/apis';
7
+import StatsChart from './component/StatsChart';
8
+import BuildSelect from '../../../components/SelectButton/BuildSelect'
7 9
 import router from 'umi/router';
8 10
 
9 11
 
10 12
 const { RangePicker } = DatePicker;
11 13
 const { Option } = Select
12 14
 
13
-
14
-// const formatDate = (start, end) => {
15
-//   const startDate = moment(start).format('YYYY-MM-DDT00:00:00.000') + 'Z'
16
-//   const endDate = moment(end).format('YYYY-MM-DDT23:59:59.999') + 'Z'
17
-//   return { startDate, endDate }
18
-// }
19
-
20 15
 let daterange = []
21 16
 let tableTitle = ['类型']
22 17
 
23
-let columns = [
24
-  {
25
-    title: '日期',
26
-    dataIndex: 'createTime',
27
-    key: 'createTime',
28
-  },
29
-  // {
30
-  //   title: '名片分享',
31
-  //   dataIndex: '名片分享',
32
-  //   key: '名片分享',
33
-  // },
34
-  // {
35
-  //   title: '生成海报',
36
-  //   dataIndex: '生成海报',
37
-  //   key: '生成海报',
38
-  // },
39
-  // {
40
-  //   title: '小程序搜索',
41
-  //   dataIndex: '小程序搜索',
42
-  //   key: '小程序搜索',
43
-  // },
44
-  // {
45
-  //   title: '好友分享',
46
-  //   dataIndex: '好友分享',
47
-  //   key: '好友分享',
48
-  // },
49
-]
50
-
51
-// let columns = [
52
-//   {
53
-//     title: '类型',
54
-//     dataIndex: 'value',
55
-//     key: 'value',
56
-//   }
57
-// ]
58
-
59 18
 class buildingStats extends React.Component {
60 19
 
61 20
   constructor(props) {
62 21
     super(props)
63 22
     this.state = {
64
-      dataSoures: [],
23
+      barData: {},
65 24
       tableData: [],
25
+      total: 0,
66 26
       userType: 'all',
67 27
       endDate: {},
68
-      startDate: {}
28
+      startDate: {},
29
+      buildingId: ''
69 30
     }
70 31
   }
71 32
 
72 33
   componentDidMount() {
73
-    this.setState({ endDate: new Date(), startDate: moment().subtract(7, 'day').toDate() })
34
+    this.getBarData(moment().subtract(7, 'day').toDate(),new Date())
35
+    this.getTableData(moment().subtract(7, 'day').toDate(),new Date(),this.state.buildingId)
36
+    this.setState({...this.state, endDate: new Date(), startDate: moment().subtract(7, 'day').toDate() })
37
+    
38
+  }
39
+
40
+  // 获取图表数据
41
+  getBarData = (startDate, endDate) => {
42
+    request({ ...apis.stats.barList, params: { startDate, endDate } }).then((data) => {
43
+        this.setState({...this.state, barData: data})
44
+      })
45
+  }
46
+
47
+  //获取表格数据
48
+  getTableData = (startDate, endDate, buildingId,pageNum,pageSize,sortField,sortOrder) => {
49
+    request({ ...apis.stats.tableList, params: { startDate, endDate, buildingId,pageNum,pageSize,sortField,sortOrder } }).then((data) => {
50
+        this.setState({...this.state, tableData: data.records, total: data.total})
51
+      })
74 52
   }
75 53
 
76 54
   formatDate = (start, end) => {
@@ -79,84 +57,122 @@ class buildingStats extends React.Component {
79 57
     return { startDate: tempStartDate, endDate: tempEndDate }
80 58
   }
81 59
 
60
+  //时间选择器改变的时候
82 61
   onChangetime = (_dates, dateStrings) => {
83
-    daterange[1] = dateStrings[1]
84
-    daterange[0] = dateStrings[0]
85
-  }
86
-
87
-  handleSubmit = (e, props) => {
88
-
89
-    e.preventDefault();
90
-
62
+    daterange[0] = `${moment(dateStrings[0]).format('YYYY-MM-DDT00:00:00.000')}Z`
63
+    daterange[1] = `${moment(dateStrings[1]).format('YYYY-MM-DDT23:59:59.999')}Z`
91 64
   }
92 65
 
66
+  //切换三个标签页
93 67
   getDataOf = (days) => {
94
-    this.setState({ endDate: new Date(), startDate: moment().subtract(days, 'day').toDate() })
68
+    this.getBarData(moment().subtract(days, 'day').toDate(),new Date())
69
+    this.getTableData(moment().subtract(days, 'day').toDate(),new Date(),this.state.buildingId)
70
+    this.setState({ ...this.state, endDate: new Date(), startDate: moment().subtract(days, 'day').toDate() })
95 71
   }
96 72
 
73
+  //点击查询
97 74
   datalist = () => {
98
-    console.log()
75
+    this.getBarData(daterange[0] === undefined ? moment().subtract(7, 'day').toDate() : daterange[0],daterange[1] === undefined ? new Date() : daterange[1])
76
+    this.getTableData(daterange[0] === undefined ? moment().subtract(7, 'day').toDate() : daterange[0],daterange[1] === undefined ? new Date() : daterange[1],this.state.buildingId)
99 77
     this.setState({ 
100
-      endDate: daterange[1] === '' ? new Date() : daterange[1],
101
-      startDate: daterange[0] === '' ? moment().subtract(7, 'day').toDate() : daterange[0],
78
+      ...this.state,
79
+      endDate: daterange[1] === undefined ? new Date() : daterange[1],
80
+      startDate: daterange[0] === undefined ? moment().subtract(7, 'day').toDate() : daterange[0],
102 81
     })
82
+    
103 83
   }
104
-
105
-  onSuccess = e => {
106
-    this.setState({ dataSoures: e }, () => {
107
-      this.onTabledatas(e)
108
-    })
84
+  
85
+  //切换楼盘信息
86
+  handleBuildingChange = (e) => {
87
+    this.getTableData(this.state.startDate,this.state.endDate,e)
88
+    this.setState({...this.state, buildingId: e})
109 89
   }
110 90
 
111
-  onTabledatas = (e) => {
112
-    console.log('this.state.userType: ', this.state.userType)
113
-    e.tdWxDicts.map(x => {
114
-        columns = columns.filter(y => y.key != x.sceneType).concat({
115
-          title: x.sceneAlias,
116
-          dataIndex: x.sceneType,
117
-          key: x.sceneType,
118
-        })
119
-    })
120
-    const data = (e.list || []).reduce((acc, item) => {
121
-      const { sceneType, fromNum, registeredNum, createTime } = item
122
-      const num = this.state.userType === 'registered' ? registeredNum : fromNum
123
-      acc[createTime] = { ...acc[createTime], ...item, [`${sceneType}`]: !num ? 0 : num }
124
-      return acc
125
-    }, {})
126
-
127
-    const dictData =  e.tdWxDicts.reduce((acc,item,index) => {
128
-      const { sceneType } = item
129
-      acc[sceneType] = 0
130
-      return acc
131
-    },{})
132
-
133
-    const tableData = Object.keys(data).map(k => data[k]).reduce((acc,item,index) => {
134
-      acc[index] = { ...dictData, ...item }
135
-      return acc
136
-    },[])
137
-
138
-    this.setState({ tableData })
139
-
91
+  //排序
92
+  handleTableChange = (pagination, filters, sorter) => {
93
+    console.log(pagination, filters, sorter)
94
+    this.getTableData(this.state.startDate,this.state.endDate,this.state.buildingId,pagination.current,10,sorter.columnKey,sorter.order)
95
+  };
96
+
97
+  //导出
98
+  exportBuildingStats = () => {
99
+    request({ ...apis.stats.buildingExport, params: { startDate: this.state.startDate, endDate: this.state.endDate, buildingId: this.state.buildingId } })
100
+      .then(data => {
101
+        if (!data) {
102
+          return
103
+        }
104
+        const url = window.URL.createObjectURL(new Blob([data]))
105
+        const link = document.createElement('a')
106
+        link.style.display = 'none'
107
+        link.href = url
108
+        link.setAttribute('download', '项目统计.xlsx')
109
+        document.body.append(link)
110
+        link.click()
111
+      }).catch(() => {
112
+
113
+      })
140 114
   }
141 115
 
142
-  handleSelectChange = (e) => {
143
-    this.setState({ userType: e }, () => {
144
-      this.onTabledatas(this.state.dataSoures)
145
-    })
116
+  //去详情页面
117
+  toDetailPage = (record) => {
118
+    router.push({
119
+      pathname: '/statistical/building/detail',
120
+      query: {
121
+        buildingId: record.buildingId,
122
+        buildingName: record.buildingName
123
+      },
124
+    });
146 125
   }
147 126
 
148
-
149 127
   render() {
128
+    const columns = [
129
+        {
130
+          title: '项目名称',
131
+          dataIndex: 'buildingName',
132
+          key: 'buildingName',
133
+        },
134
+        {
135
+          title: '新增客户',
136
+          dataIndex: 'khNum',
137
+          key: 'kh_num',
138
+          sorter: true,
139
+        },
140
+        {
141
+          title: '公客',
142
+          dataIndex: 'gkNum',
143
+          key: 'gk_num',
144
+          sorter: true,
145
+        },
146
+        {
147
+          title: '私客',
148
+          dataIndex: 'skNum',
149
+          key: 'sk_num',
150
+          sorter: true,
151
+        },
152
+        {
153
+            title: '访问人数',
154
+            dataIndex: 'uvNum',
155
+            key: 'uv_num',
156
+            sorter: true,
157
+        },
158
+        {
159
+            title: '访问次数',
160
+            dataIndex: 'pvNum',
161
+            key: 'pv_num',
162
+            sorter: true,
163
+        },
164
+        {
165
+            title: '详情',
166
+            render: (_, record) => (
167
+                    <Button type="link" style={{ color: 'red' }} onClick={() => this.toDetailPage(record)}>查看详情</Button>
168
+                ),
169
+        },
170
+      ];
171
+
150 172
     return (
151
-    <>
152
-      <div style={{
153
-        backgroundColor: '#fff',
154
-        padding: '32PX 28px',
155
-        boxShadow: '0px 0px 16px 2px rgba(0,0,0,0.12)',
156
-        borderRadius: '12px',
157
-        minHeight: '60vh'
158
-      }}>
159
-        <Radio.Group buttonStyle="solid" defaultValue="a">
173
+    <div>
174
+      <Radio.Group buttonStyle="solid" defaultValue="a">
175
+          <Radio.Button value="c" onClick={() => this.getDataOf(0)}>今日</Radio.Button>
160 176
           <Radio.Button value="a" onClick={() => this.getDataOf(7)}>最近7天</Radio.Button>
161 177
           <Radio.Button value="b" onClick={() => this.getDataOf(30)}>最近1月</Radio.Button>
162 178
         </Radio.Group>
@@ -166,24 +182,42 @@ class buildingStats extends React.Component {
166 182
             Today: [moment(), moment()],
167 183
             'This Month': [moment().startOf('month'), moment().endOf('month')],
168 184
           }}
169
-          // showTime
170
-          // format="YYYY/MM/DD HH:mm:ss"
171 185
           onChange={(_dates, dateStrings) => this.onChangetime(_dates, dateStrings)}
172 186
         />
173 187
         <Button type="primary" htmlType="submit" style={{ marginLeft: '30px' }} onClick={() => this.datalist()}>
174 188
           查询
175 189
         </Button>
176
-        <Button type="danger" onClick={() => router.go(-1)} style={{ marginBottom: '18px', marginLeft: '30px' }}>返回</Button>
177
-        <div>
178
-          <Select style={{ width: '180px' }} placeholder="所有用户" onChange={(e) => this.handleSelectChange(e)}>
179
-            <Option value='all'>所有用户</Option>
180
-            <Option value='registered'>注册用户</Option>
181
-          </Select>
182
-  
183
-          <Table style={{marginTop:'20px'}} dataSource={this.state.tableData} columns={columns} pagination={false} scroll={{ y: 500 }}></Table>
184
-        </div>
185
-      </div>
186
-    </>
190
+        <Button type="danger" onClick={() => router.go(-1)} style={{ marginBottom: '18px', marginLeft: '30px' }}>重置</Button>
191
+
192
+        <Row>
193
+            <Col span={12}>
194
+                <StatsChart title="项目公客排行" data={this.state.barData.gkBarMap} />
195
+            </Col>
196
+            <Col span={12}>
197
+                <StatsChart title="项目私客排行" data={this.state.barData.skBarMap} />
198
+            </Col>
199
+        </Row>
200
+        <Row>
201
+            <Col span={12}>
202
+                <StatsChart title="项目访问人数排行" subtext="项目详情访问情况" data={this.state.barData.wgBarMap} />
203
+            </Col>
204
+            <Col span={12}>
205
+                <StatsChart title="项目访问次数排行" subtext="项目详情访问情况,与上方时间筛选无关" data={this.state.barData.fwBarMap} />
206
+            </Col>
207
+        </Row>
208
+        <Row>
209
+            <Col span={22}>
210
+              <span style={{marginRight: '10px'}} >详细数据</span>
211
+              <BuildSelect slot='action' onChange={(e => this.handleBuildingChange(e))} value={this.state.buildingId}></BuildSelect>
212
+            </Col>
213
+            <Col span={2}>
214
+              <Button type="primary" onClick={this.exportBuildingStats}>导出</Button>
215
+            </Col>
216
+        </Row>
217
+        
218
+        
219
+        <Table style={{marginTop:'20px'}} dataSource={this.state.tableData} columns={columns} pagination={{ total: this.state.total}} onChange={this.handleTableChange} scroll={{ y: 500 }}></Table>
220
+    </div>
187 221
     )
188 222
   }
189 223
 }

+ 226
- 0
src/pages/statistical/consultant/index.jsx Voir le fichier

@@ -0,0 +1,226 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Button, DatePicker, Table, Pagination, Radio, Typography } from 'antd';
3
+import router from 'umi/router';
4
+import moment from 'moment';
5
+import BuildSelect from '../../../components/SelectButton/BuildSelect'
6
+import apis from '../../../services/apis';
7
+import request from '../../../utils/request'
8
+
9
+/**
10
+  @param {*} props
11
+  @returns
12
+ */
13
+const { RangePicker } = DatePicker;
14
+const { Text } = Typography;
15
+
16
+function record(props) {
17
+    const { getFieldDecorator } = props.form
18
+
19
+    // 获取初始化数据
20
+    const [data, setData] = useState({})
21
+
22
+    useEffect(() => {
23
+        getList({ pageNum: 1, pageSize: 10 });
24
+    }, [])
25
+
26
+    // 查询列表
27
+    const getList = (params) => {
28
+        request({ ...apis.activity.saleCountList, params: { ...params }, }).then((data) => {
29
+            setData(data)
30
+            console.log("data:", data)
31
+        })
32
+    }
33
+
34
+    //重置搜索
35
+    function handleReset() {
36
+        props.form.resetFields();
37
+    }
38
+
39
+    // 分享详情
40
+    function shareCount(personId) {
41
+        router.push({
42
+            pathname: '/record/share/shareCountList',
43
+            query: {
44
+                id: personId,
45
+            },
46
+        });
47
+    }
48
+
49
+    // 点击人数详情
50
+    function clickCount(personId) {
51
+        router.push({
52
+            pathname: '/record/share/clickCountList',
53
+            query: {
54
+                id: personId,
55
+            },
56
+        });
57
+    }
58
+
59
+    // 提交事件
60
+    const handleSubmit = (e, props) => {
61
+        e.preventDefault();
62
+        props.form.validateFields((err, values) => {
63
+            if (!err) {
64
+                let { shareTime, receiveTime, ...submitValue } = values
65
+                if (null != shareTime && shareTime.length > 0) {
66
+                    const [startCreateDate, endCreateDate] = shareTime
67
+                    submitValue.startCreateDate = moment(startCreateDate).format('YYYY-MM-DD');
68
+                    submitValue.endCreateDate = moment(endCreateDate).format('YYYY-MM-DD');
69
+                } else {
70
+                    submitValue.startCreateDate = null
71
+                    submitValue.endCreateDate = null
72
+                }
73
+                console.log(submitValue)
74
+                getList({ pageNum: 1, pageSize: 10, ...submitValue })
75
+            }
76
+        });
77
+    }
78
+
79
+    const changePageNum = (pageNumber) => {
80
+        props.form.validateFields((err, values) => {
81
+            if (!err) {
82
+                let { shareTime, receiveTime, ...submitValue } = values
83
+                if (null != shareTime && shareTime.length > 0) {
84
+                    const [startCreateDate, endCreateDate] = shareTime
85
+                    submitValue.startCreateDate = moment(startCreateDate).format('YYYY-MM-DD');
86
+                    submitValue.endCreateDate = moment(endCreateDate).format('YYYY-MM-DD');
87
+                } else {
88
+                    submitValue.startCreateDate = null
89
+                    submitValue.endCreateDate = null
90
+                }
91
+                getList({ pageNum: pageNumber, pageSize: 10, ...submitValue })
92
+            }
93
+        });
94
+    }
95
+    function getDataOf(days) {
96
+        // this.setState({ endDate: new Date(), startDate: moment().subtract(days, 'day').toDate() })
97
+    }
98
+    const columns = [
99
+
100
+        {
101
+            title: '项目',
102
+            dataIndex: 'buildingName',
103
+            key: 'buildingName',
104
+            align: 'center',
105
+        },
106
+        {
107
+            title: '置业顾问名称1',
108
+            dataIndex: 'consultantName',
109
+            key: 'consultantName',
110
+            align: 'center',
111
+        },
112
+        {
113
+            title: '置业顾问电话',
114
+            dataIndex: 'consultantPhone',
115
+            key: 'consultantPhone',
116
+            align: 'center',
117
+        },
118
+        {
119
+            title: '客户总计',
120
+            dataIndex: 'customerAggregate',
121
+            key: 'customerAggregate',
122
+            align: 'center',
123
+            sorter: (a, b) => a.customerAggregate - b.customerAggregate,
124
+            render: (_, record) => <><span style={{ color: 'blue', cursor: 'pointer' }} onClick={() => shareCount(record.personId)} >{record.customerAggregate}</span></>,
125
+        },
126
+        {
127
+            title: '新增客户',
128
+            dataIndex: 'newCustomers',
129
+            key: 'newCustomers',
130
+            align: 'center',
131
+            sorter: (a, b) => a.newCustomers - b.newCustomers,
132
+            render: (_, record) => <><span style={{ color: 'blue', cursor: 'pointer' }} onClick={() => shareCount(record.personId)} >{record.newCustomers}</span></>,
133
+        },
134
+        {
135
+            title: '分享次数',
136
+            dataIndex: 'shareCount',
137
+            key: 'shareCount',
138
+            align: 'center',
139
+            sorter: (a, b) => a.shareCount - b.shareCount,
140
+            render: (_, record) => <><span style={{ color: 'blue', cursor: 'pointer' }} onClick={() => shareCount(record.personId)} >{record.shareCount}</span></>,
141
+        },
142
+        {
143
+            title: '分享访问人数',
144
+            dataIndex: 'shareVisitPersonNum',
145
+            key: 'shareVisitPersonNum',
146
+            align: 'center',
147
+            sorter: (a, b) => a.shareVisitPersonNum - b.shareVisitPersonNum,
148
+            render: (_, record) => <><span style={{ color: 'blue', cursor: 'pointer' }} onClick={() => shareCount(record.personId)} >{record.shareVisitPersonNum}</span></>,
149
+        },
150
+        {
151
+            title: '分享访问次数',
152
+            dataIndex: 'shareVisitNum',
153
+            key: 'shareVisitNum',
154
+            align: 'center',
155
+            sorter: (a, b) => a.shareVisitNum - b.shareVisitNum,
156
+            render: (_, record) => <><span style={{ color: 'blue', cursor: 'pointer' }} onClick={() => shareCount(record.personId)} >{record.shareVisitNum}</span></>,
157
+        },
158
+
159
+        {
160
+            title: '分享拓客',
161
+            dataIndex: 'sharePossess',
162
+            key: 'sharePossess',
163
+            align: 'center',
164
+            sorter: (a, b) => a.sharePossess - b.sharePossess,
165
+            render: (_, record) => <><span style={{ color: 'blue', cursor: 'pointer' }} onClick={() => clickCount(record.personId)} >{record.sharePossess}</span></>,
166
+        },
167
+        {
168
+            title: '主页访问人数',
169
+            dataIndex: 'visitPerson',
170
+            key: 'visitPerson',
171
+            align: 'center',
172
+            sorter: (a, b) => a.visitPerson - b.visitPerson,
173
+            render: (_, record) => <><span style={{ color: 'blue', cursor: 'pointer' }} onClick={() => clickCount(record.personId)} >{record.visitPerson}</span></>,
174
+        },
175
+        {
176
+            title: '主页访问次数',
177
+            dataIndex: 'clickNum',
178
+            key: 'clickNum',
179
+            align: 'center',
180
+            sorter: (a, b) => a.clickNum - b.clickNum,
181
+            render: (_, record) => <><span style={{ color: 'blue', cursor: 'pointer' }} onClick={() => clickCount(record.personId)} >{record.clickNum}</span></>,
182
+        },
183
+    ];
184
+
185
+
186
+
187
+    return (
188
+
189
+        <>
190
+            <Form layout="inline" onSubmit={e => handleSubmit(e, props)}>
191
+                <div style={{ display: 'flex', alignItems: 'center' }}>
192
+                    <Radio.Group buttonStyle="solid" defaultValue="a" style={{ marginRight: '16px', }}>
193
+                        <Radio.Button value="a" onClick={getDataOf(7)}>最近7天</Radio.Button>
194
+                        <Radio.Button value="b" onClick={getDataOf(30)}>最近1月</Radio.Button>
195
+                    </Radio.Group>
196
+                    <Form.Item>
197
+                        {getFieldDecorator('shareTime')(
198
+                            <RangePicker placeholder={['开始日期', '结束日期']} />
199
+                        )}
200
+                    </Form.Item>
201
+                    <Form.Item>
202
+                        {getFieldDecorator('buildingId')(
203
+                            <BuildSelect />,
204
+                        )}
205
+                    </Form.Item>
206
+                    <Form.Item style={{ position: 'absolute', right: '38px' }}>
207
+                        <Button type="primary" onClick={handleReset}>查询</Button>
208
+                        <Button style={{ marginLeft: 8 }} onClick={handleReset}>重置</Button>
209
+                    </Form.Item>
210
+                </div>
211
+            </Form>
212
+            <Table rowKey="KPIRecords"
213
+                style={{ marginTop: '30px' }}
214
+                dataSource={data.records}
215
+                columns={columns}
216
+                pagination={false}
217
+            />
218
+            < div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '30px' }}>
219
+                <Pagination showQuickJumper defaultCurrent={1} total={data.total} onChange={changePageNum} current={data.current} />
220
+            </div>
221
+        </>
222
+    )
223
+}
224
+const WrappedHeader = Form.create({ name: 'record' })(record);
225
+
226
+export default WrappedHeader

+ 32
- 0
src/services/apis.js Voir le fichier

@@ -1593,4 +1593,36 @@ export default {
1593 1593
       action: 'admin.contract.list.get',
1594 1594
     },
1595 1595
   },
1596
+  stats: {
1597
+    barList: {
1598
+      method: 'GET',
1599
+      url: `${prefix}/stats/barList`,
1600
+      action: 'admin.contract.list.get',
1601
+    },
1602
+    tableList: {
1603
+      method: 'GET',
1604
+      url: `${prefix}/stats/tableList`,
1605
+      action: 'admin.contract.list.get',
1606
+    },
1607
+    buildingExport: {
1608
+      method: 'GET',
1609
+      url: `${prefix}/stats/buildingExport`,
1610
+      action: 'admin.contract.list.get',
1611
+    },
1612
+    timeBarList: {
1613
+      method: 'GET',
1614
+      url: `${prefix}/stats/timeBarList`,
1615
+      action: 'admin.contract.list.get',
1616
+    },
1617
+    timeTableList: {
1618
+      method: 'GET',
1619
+      url: `${prefix}/stats/timeTableList`,
1620
+      action: 'admin.contract.list.get',
1621
+    },
1622
+    buildingTimeExport: {
1623
+      method: 'GET',
1624
+      url: `${prefix}/stats/buildingTimeExport`,
1625
+      action: 'admin.contract.list.get',
1626
+    }
1627
+  }
1596 1628
 }