Browse Source

add some reports

张延森 5 years ago
parent
commit
c5fb7d4798

+ 11
- 5
src/components/HeaderCell.vue View File

@@ -1,6 +1,11 @@
1 1
 <template>
2 2
   <div class="header-cell">
3
-    <slot></slot>
3
+    <div class="body">
4
+      <slot></slot>
5
+    </div>
6
+    <div class="action">
7
+
8
+    </div>
4 9
     <slot name="action"></slot>
5 10
   </div>
6 11
 </template>
@@ -14,13 +19,14 @@ export default {
14 19
 <style lang="scss" scoped>
15 20
 .header-cell {
16 21
   display: flex;
22
+  align-items: center;
17 23
 
18
-  &:first-child {
19
-    flex: auto;
24
+  .action {
25
+    flex: none;
20 26
   }
21 27
 
22
-  &>* {
23
-    flex: none;
28
+  .body {
29
+    flex: auto;
24 30
   }
25 31
 }
26 32
 </style>

+ 34
- 10
src/components/charts/XLine.vue View File

@@ -1,8 +1,8 @@
1 1
 <template>
2
-  <v-chart :options="options" />
2
+  <div ref="echart" ></div>
3 3
 </template>
4 4
 <script>
5
-import ECharts from 'vue-echarts'
5
+import Echarts from "echarts";
6 6
 
7 7
 export default {
8 8
   name: "XLine",
@@ -12,11 +12,9 @@ export default {
12 12
       default: () => {},
13 13
     },
14 14
   },
15
-  components: {
16
-    'v-chart': ECharts,
17
-  },
18 15
   data() {
19 16
     return {
17
+      chart: undefined,
20 18
       defaultOpts: {
21 19
         title: {
22 20
           text: "新增用户"
@@ -57,12 +55,38 @@ export default {
57 55
       }
58 56
     };
59 57
   },
60
-  computed: {
61
-    options() {
62
-      return {
63
-        ...this.defaultOpts,
64
-        ...(this.value || {}),
58
+  watch: {
59
+    value: {
60
+      handler(val) {
61
+        this.renderChart(val)
62
+      },
63
+      immediate: true,
64
+      deep: true,
65
+    },
66
+  },
67
+  mounted() {
68
+    this.renderChart(this.value || {})
69
+  },
70
+  methods: {
71
+    initChats () {
72
+      if (!this.chart && this.$refs.echart) {
73
+        this.chart = Echarts.init(this.$refs.echart);
74
+      }
75
+
76
+      if (this.chart) {
77
+        return Promise.resolve(this.chart)
78
+      } else {
79
+        return Promise.reject()
65 80
       }
81
+    },
82
+    renderChart(val) {
83
+      this.initChats().then((echart) => {
84
+        // 绘制图表
85
+        echart.setOption({
86
+          ...this.defaultOpts,
87
+          ...val
88
+        });
89
+      })
66 90
     }
67 91
   }
68 92
 };

+ 12
- 8
src/config/api.js View File

@@ -337,14 +337,18 @@ const apis = {
337 337
       method:'get',
338 338
       url: `${commPrefix}/indexStatistical`
339 339
     },
340
-      userResource: {
341
-          method:'get',
342
-          url: `${commPrefix}/selectUserResource`
343
-      },
344
-      newsUserCount: {
345
-          method:'get',
346
-          url: `${commPrefix}/selectNewsUserCount`
347
-      },
340
+    userResource: {
341
+        method:'get',
342
+        url: `${commPrefix}/selectUserResource`
343
+    },
344
+    newsUserCount: {
345
+        method:'get',
346
+        url: `${commPrefix}/selectNewsUserCount`
347
+    },
348
+    userConversion: {
349
+      method:'get',
350
+      url: `${commPrefix}/selectConversion`
351
+    },
348 352
   },
349 353
 }
350 354
 export default apis

+ 17
- 0
src/store/modules/indexEcharts.js View File

@@ -19,6 +19,23 @@ export default {
19 19
     setDetailNull ({ commit }) {
20 20
       commit('updateList', {})
21 21
     },
22
+
23
+    getUserConversionRate(_, payload) {
24
+      return new Promise((resolve, reject) => {
25
+        request({
26
+          ...apis.indexEcharts.userConversion,
27
+          params: payload,
28
+        }).then((data) => {
29
+          resolve(data)
30
+        }).catch((err) => {
31
+          const message = err.message || err.msg
32
+          if (typeof message === 'string') {
33
+            reject(message)
34
+          }
35
+        })
36
+      })
37
+    },
38
+
22 39
     getIndexEcharts ({ commit }, payload) {
23 40
       return new Promise((resolve, reject) => {
24 41
         request({

+ 32
- 0
src/views/indexEcharts/components/IntentionalCustomers.vue View File

@@ -0,0 +1,32 @@
1
+<template>
2
+  <div class="chart-box">
3
+    <header-cell>
4
+      <h3>意向客户</h3>
5
+      <select-building slot="action"></select-building>
6
+    </header-cell>
7
+
8
+    <el-table :data="tableData"  border  center  style="width: 100%; margin-top: 16px">
9
+      <el-table-column label="用户姓名" prop="name"></el-table-column>
10
+      <el-table-column label="手机号" prop="phone"></el-table-column>
11
+      <el-table-column label="意向楼盘" prop="building"></el-table-column>
12
+      <el-table-column label="意向值" prop="num"></el-table-column>
13
+    </el-table>
14
+  </div>
15
+</template>
16
+
17
+<script>
18
+export default {
19
+  name: 'IntentionalCustomers',
20
+  props: ['value'],
21
+  components: {
22
+    HeaderCell: () => import('@/components/HeaderCell'),
23
+  },
24
+  computed: {
25
+    tableData() {
26
+      return this.value || []
27
+    }
28
+  }
29
+}
30
+</script>
31
+
32
+<style lang="scss" src="./style.scss"></style>

+ 41
- 0
src/views/indexEcharts/components/NewUsers.vue View File

@@ -0,0 +1,41 @@
1
+<template>
2
+  <div class="chart-box">
3
+    <h3>新增客户 <small>最近七天</small></h3>
4
+    <el-table :data="tableData"  border  center  style="width: 100%; margin-top: 16px">
5
+      <el-table-column v-for="(item, index) in tableTitle" :key="index" :label="item" :prop="index == 0 ? 'label': item"></el-table-column>
6
+    </el-table>
7
+  </div>
8
+</template>
9
+
10
+<script>
11
+export default {
12
+  name: 'NewUsers',
13
+  props: ['value'],
14
+  data () {
15
+    return {
16
+      tableTitle: [ '类型' ],
17
+    }
18
+  },
19
+  computed: {
20
+    tableData () {
21
+      return (this.value || []).reduce((acc, item, index) => {
22
+          const { date, userCount, authorizationCount } = item
23
+          const row1 = {
24
+            ...acc[0],
25
+            [`${date}`]: userCount,
26
+          }
27
+          const row2 = {
28
+            ...acc[1],
29
+            [`${date}`]: authorizationCount,
30
+          }
31
+
32
+          this.tableTitle = this.tableTitle.concat(`${date}`) // eslint-disable-line
33
+
34
+          return [row1, row2];          
35
+        }, [{ label: '新增用户', }, { label: '授权注册', } ])
36
+    }
37
+  }
38
+}
39
+</script>
40
+
41
+<style lang="scss" src="./style.scss"></style>

+ 45
- 0
src/views/indexEcharts/components/UserActive.vue View File

@@ -0,0 +1,45 @@
1
+<template>
2
+  <div class="chart-box">
3
+    <h3>活跃用户数</h3>
4
+    <v-chart class="chart" :options="options" />
5
+  </div>
6
+</template>
7
+
8
+<script>
9
+import ECharts from 'vue-echarts'
10
+import 'echarts/lib/chart/bar'
11
+import 'echarts/lib/component/tooltip'
12
+
13
+export default {
14
+  name: 'UserActive',
15
+  components: {
16
+    'v-chart': ECharts,
17
+  },
18
+  props: [ 'value' ],
19
+  data () {
20
+    return {
21
+      defaultOpt: {
22
+        legend: { show: false },
23
+        color: ['#8954BA', '#175DFB', '#0BB963', '#27DEFF', '#E713D2', '#E71313'],
24
+        tooltip: {},
25
+        xAxis: { type: 'time' },
26
+        yAxis: {},
27
+      },
28
+    }
29
+  },
30
+  computed: {
31
+    options () {
32
+      return {
33
+        ...this.defaultOpt,
34
+        series: {
35
+          type: 'bar',
36
+          name: '活跃用户',
37
+          data: (this.value || []).map(x => ([ x.date,!x.activityCount ? 0 : x.activityCount ]))
38
+        }
39
+      }
40
+    }
41
+  }
42
+}
43
+</script>
44
+
45
+<style lang="scss" src="./style.scss"></style>

+ 66
- 0
src/views/indexEcharts/components/UserBehavior.vue View File

@@ -0,0 +1,66 @@
1
+<template>
2
+  <div class="chart-box">
3
+    <header-cell>
4
+      <h3>用户行为 <small>最近七天</small></h3>
5
+      <select-building slot="action"></select-building>
6
+    </header-cell>
7
+    <v-chart class="chart" :options="options" />
8
+  </div>
9
+</template>
10
+
11
+<script>
12
+import ECharts from 'vue-echarts'
13
+import 'echarts/lib/chart/line'
14
+import 'echarts/lib/component/tooltip'
15
+import dayjs from 'dayjs'
16
+import HeaderCell from '@/components/HeaderCell'
17
+
18
+export default {
19
+  name: 'UserBehavior',
20
+  components: {
21
+    'v-chart': ECharts,
22
+    HeaderCell,
23
+  },
24
+  props: [
25
+    'value',
26
+  ],
27
+  data() {
28
+    return {
29
+      baseOpt: {
30
+        legend: {},
31
+        color: ['#8954BA', '#175DFB', '#0BB963', '#27DEFF', '#E713D2', '#E71313'],
32
+        tooltip: {},
33
+        xAxis: { type: 'time' },
34
+        yAxis: {},
35
+      },
36
+    }
37
+  },
38
+  computed: {
39
+    options() {
40
+      const seriesMaker = (this.value || []).reduce((series, item) => {
41
+        let { date, activityCount, activity } = item
42
+        date = dayjs(date).format('YYYY-MM-DD')
43
+        if (!activityCount) activityCount = 0
44
+
45
+        // 使用对象, 可以去重
46
+        series[`${activity}`] = (series[`${activity}`] || []).concat([[ date, activityCount ]])
47
+
48
+        return series;
49
+      }, {})
50
+
51
+      return {
52
+        ...this.baseOpt,
53
+        series: Object.keys(seriesMaker).map(x => {
54
+          return {
55
+            type: 'line',
56
+            name: x,
57
+            data: seriesMaker[x],
58
+          }
59
+        }),
60
+      }
61
+    }
62
+  },
63
+}
64
+</script>
65
+
66
+<style lang="scss" src="./style.scss"></style>

+ 48
- 0
src/views/indexEcharts/components/UserCity.vue View File

@@ -0,0 +1,48 @@
1
+<template>
2
+  <div class="chart-box">
3
+    <h3>城市分布</h3>
4
+    <v-chart class="chart" :options="options" />
5
+  </div>
6
+</template>
7
+
8
+<script>
9
+import ECharts from 'vue-echarts'
10
+import 'echarts/lib/chart/pie'
11
+import 'echarts/lib/component/tooltip'
12
+
13
+export default {
14
+  name: 'UserCity',
15
+  components: {
16
+    'v-chart': ECharts,
17
+  },
18
+  props: [
19
+    'value',
20
+  ],
21
+  data() {
22
+    return {
23
+      defaultOpt: {
24
+        legend: {},
25
+        color: ['#8954BA', '#175DFB', '#0BB963', '#27DEFF', '#E713D2', '#E71313'],
26
+        tooltip: {},
27
+        series: {
28
+          type: 'pie',
29
+          name: '城市分布',
30
+        }
31
+      },
32
+    }
33
+  },
34
+  computed: {
35
+    options() {
36
+      return {
37
+        ...this.defaultOpt,
38
+        series: {
39
+          ...this.defaultOpt.series,
40
+          data: this.value || [],
41
+        },
42
+      }
43
+    }
44
+  },
45
+}
46
+</script>
47
+
48
+<style lang="scss" src="./style.scss"></style>

+ 108
- 0
src/views/indexEcharts/components/UserConversion.vue View File

@@ -0,0 +1,108 @@
1
+<template>
2
+  <div class="chart-box">
3
+    <header-cell>
4
+      <h3>转化率</h3>
5
+      <el-select v-model="theStatis" @change="getData" slot="action">
6
+        <el-option v-for="item in statisTypes" :label="item.label" :value="item.value" :key="item.value"></el-option>
7
+      </el-select>
8
+    </header-cell>
9
+    <v-chart class="chart" :options="options" />
10
+  </div>
11
+</template>
12
+
13
+<script>
14
+import ECharts from 'vue-echarts'
15
+import 'echarts/lib/chart/pie'
16
+import 'echarts/lib/component/tooltip'
17
+import { createNamespacedHelpers } from "vuex"
18
+
19
+const { mapActions } = createNamespacedHelpers("indexEcharts");
20
+
21
+export default {
22
+  name: 'UserConversion',
23
+  components: {
24
+    'v-chart': ECharts,
25
+    HeaderCell: () => import('@/components/HeaderCell'),
26
+  },
27
+  props: [ 'value' ],
28
+  data () {
29
+    return {
30
+      defaultOpt: {
31
+        legend: {},
32
+        color: ['#8B7FE2', '#DDDDDD'],
33
+        tooltip: {},
34
+        series: {
35
+          type: 'pie',
36
+          name: '转化率',
37
+          radius: ['50%', '70%'],
38
+        }
39
+      },
40
+
41
+      theStatis : 'building_save',
42
+      theCurrent: [],
43
+      statisTypes: [
44
+        { label: '项目收藏', value: 'building_save' },
45
+        { label: '项目转发', value: 'building_share' },
46
+        { label: '活动收藏', value: 'activity_save' },
47
+        { label: '活动转发', value: 'activity_share' },
48
+        { label: '资讯收藏', value: 'news_save' },
49
+        { label: '资讯转发', value: 'news_share' },
50
+        { label: '活动报名', value: 'activity_sign' },
51
+        { label: '授权手机', value: 'authorization_phone' },
52
+      ],
53
+      // 各统计结果
54
+      dataset: {},
55
+    }
56
+  },
57
+  computed: {
58
+    options () {
59
+      return {
60
+        ...this.defaultOpt,
61
+        series: {
62
+          ...this.defaultOpt.series,
63
+          data: this.theCurrent,
64
+        }
65
+      }
66
+    }
67
+  },
68
+  methods: {
69
+    ...mapActions(['getUserConversionRate']),
70
+    getData(e) {
71
+      if (!this.dataset[e]) {
72
+        this.getUserConversionRate({ conversion: e }).then(this.setDataset)
73
+      } else {
74
+        this.theCurrent = this.dataset[e]
75
+      }
76
+    },
77
+    setDataset(data) {      
78
+      const { pvNum, ...other } = data['data_count']
79
+
80
+      // 获取第一个值
81
+      let num = 0
82
+      for (let v of Object.keys(other)) {
83
+        num = other[v]
84
+        break
85
+      }
86
+
87
+      if (pvNum < num) {
88
+        this.theCurrent = []
89
+      } else {
90
+        this.theCurrent = [
91
+          { name: this.getStatisName(), value: num },
92
+          { name: '其余', value: pvNum - num },
93
+        ]
94
+      }
95
+      
96
+      this.dataset[this.theStatis] = this.theCurrent
97
+    },
98
+    getStatisName() {
99
+      return this.statisTypes.filter(x => x.value === this.theStatis)[0].label
100
+    }
101
+  },
102
+  mounted () {
103
+    this.getUserConversionRate({ conversion: this.theStatis }).then(this.setDataset)
104
+  }
105
+}
106
+</script>
107
+
108
+<style lang="scss" src="./style.scss"></style>

+ 49
- 0
src/views/indexEcharts/components/UserSex.vue View File

@@ -0,0 +1,49 @@
1
+<template>
2
+  <div class="chart-box">
3
+    <h3>性别比例</h3>
4
+    <v-chart class="chart" :options="options" />
5
+  </div>
6
+</template>
7
+
8
+<script>
9
+import ECharts from 'vue-echarts'
10
+import 'echarts/lib/chart/pie'
11
+import 'echarts/lib/component/tooltip'
12
+
13
+export default {
14
+  name: 'UserSex',
15
+  components: {
16
+    'v-chart': ECharts,
17
+  },
18
+  props: [
19
+    'value',
20
+  ],
21
+  data() {
22
+    return {
23
+      defaultOpt: {
24
+        legend: {},
25
+        color: ['#6A96F8', '#F5749E'],
26
+        tooltip: {},
27
+        series: {
28
+          type: 'pie',
29
+          name: '性别比例',
30
+          radius: ['50%', '70%'],
31
+        }
32
+      },
33
+    }
34
+  },
35
+  computed: {
36
+    options() {
37
+      return {
38
+        ...this.defaultOpt,
39
+        series: {
40
+          ...this.defaultOpt.series,
41
+          data: this.value || [],
42
+        },
43
+      }
44
+    }
45
+  },
46
+}
47
+</script>
48
+
49
+<style lang="scss" src="./style.scss"></style>

+ 94
- 12
src/views/indexEcharts/components/UsrSRCLineAndPie.vue View File

@@ -1,26 +1,108 @@
1 1
 <template>
2
-  <header-cell>
3
-    <div>
4
-      <x-line ></x-line>
5
-    </div>
6
-    <div slot="action">
7
-
8
-    </div>
9
-  </header-cell>
2
+  <div class="chart-box">
3
+    <h3>用户来源 <small>最近七天</small></h3>
4
+    <v-chart class="chart" :options="options" />
5
+  </div>
10 6
 </template>
11 7
 
12 8
 <script>
9
+import ECharts from 'vue-echarts'
10
+import 'echarts/lib/chart/bar'
11
+import 'echarts/lib/component/tooltip'
12
+
13 13
 export default {
14 14
   name: 'UsrSRCLineAndPie',
15 15
   components: {
16
-    HeaderCell: () => import('@/components/HeaderCell'),
17
-    XLine: () => import('@/components/XLine'),
16
+    'v-chart': ECharts,
18 17
   },
18
+  props: [
19
+    'value',
20
+  ],
19 21
   data () {
20 22
     return {
21
-      title: { text: '用户来源', subtext: '最近七天' }
23
+      baseOpts: {
24
+        legend: {},
25
+        color: ['#286DD0', '#8565CE', '#6A96F8', '#F5749E', '#8B7FE2'],
26
+        tooltip: {},
27
+        yAxis: {},
28
+        grid: [
29
+          { right: '50%' },
30
+          { right: '5%' }
31
+        ],
32
+      },
22 33
     }
23
-  }
34
+  },
35
+  computed: {
36
+    // 柱图
37
+    barOptions () {
38
+      const source = (this.value || {}).columnar || [];
39
+      return {
40
+        xAxis: { type: 'category' },
41
+        legend: {
42
+          left: '20%',
43
+          data: ['所有用户', '注册用户'],
44
+        },
45
+        series: [
46
+          { type: 'bar', name: '所有用户', datasetIndex: 0 },
47
+          { type: 'bar', name: '注册用户' },
48
+        ],
49
+        dataset: {
50
+          id: 'bar',
51
+          dimensions: [ 'fromName', 'userCount', 'registered' ],
52
+          source: source,
53
+        },
54
+      }
55
+    },
56
+    // 饼图
57
+    pieOptions () {
58
+      const { person_estate_agent = 0, person_null = 0, person_realty_consultant = 0 } = (this.value || {}).pie || {};
59
+      return {
60
+        xAxis: {},
61
+        legend: {
62
+          left: '70%',
63
+          data: ['来源置业顾问', '来源全民经纪人', '自主进入'],
64
+        },
65
+        series: [
66
+          {
67
+            type: 'pie',
68
+            datasetIndex: 1,
69
+            center: ['75%', '50%'],
70
+            radius: [0, '50%'],
71
+          },
72
+        ],
73
+        dataset: {
74
+          id: 'pie',
75
+          source: [
76
+            { form: '来源置业顾问', value: person_realty_consultant },
77
+            { form: '来源全民经纪人', value: person_estate_agent },
78
+            { form: '自主进入', value: person_null },
79
+          ]
80
+        },
81
+      }
82
+    },
83
+    options() {
84
+      return {
85
+        ...this.baseOpts,
86
+        xAxis: [
87
+          this.barOptions.xAxis,
88
+          this.pieOptions.xAxis,
89
+        ],
90
+        legend: [
91
+          this.barOptions.legend,
92
+          this.pieOptions.legend,
93
+        ],
94
+        series: [
95
+          ...this.barOptions.series,
96
+          ...this.pieOptions.series,
97
+        ],
98
+        dataset: [
99
+          this.barOptions.dataset,
100
+          this.pieOptions.dataset,
101
+        ],
102
+      }
103
+    }
104
+  },
24 105
 }
25 106
 </script>
26 107
 
108
+<style lang="scss" src="./style.scss"></style>

+ 63
- 0
src/views/indexEcharts/components/VBar.vue View File

@@ -0,0 +1,63 @@
1
+<template>
2
+  <v-chart :options="opts" />
3
+</template>
4
+
5
+<script>
6
+import ECharts from 'vue-echarts'
7
+import 'echarts/lib/chart/bar'
8
+
9
+const times = (x) => {
10
+  const arr = []
11
+
12
+  for (let i = 0; i ++; i < x) {
13
+    arr.push(undefined)
14
+  }
15
+
16
+  return arr
17
+}
18
+
19
+export default {
20
+  name: 'VBar',
21
+  props: {
22
+    options: Object,
23
+    labels: Array,
24
+    num: {
25
+      type: Number,
26
+      default: 1,
27
+    }
28
+  },
29
+  components: {
30
+    'v-chart': ECharts,
31
+  },
32
+  data() {
33
+    return {
34
+      defaultOpts: {
35
+        legend: {},
36
+        tooltip: {},
37
+        xAxis: {},
38
+        yAxis: {},
39
+      }
40
+    };
41
+  },
42
+  computed: {
43
+    opts() {
44
+      let series = (this.labels || []).map((it, inx) => {
45
+        return {
46
+          type: 'bar',
47
+          name: it,
48
+        }
49
+      })
50
+
51
+      if (!series || !series.length) {
52
+        series = times(this.num).map(() => ({ type: 'bar' }))
53
+      }
54
+
55
+      return {
56
+        ...this.defaultOpts,
57
+        series,
58
+        ...(this.options || {}),
59
+      }
60
+    }
61
+  }
62
+}
63
+</script>

+ 63
- 0
src/views/indexEcharts/components/VLine.vue View File

@@ -0,0 +1,63 @@
1
+<template>
2
+  <v-chart :options="opts" />
3
+</template>
4
+
5
+<script>
6
+import ECharts from 'vue-echarts'
7
+import 'echarts/lib/chart/line'
8
+
9
+const times = (x) => {
10
+  const arr = []
11
+
12
+  for (let i = 0; i ++; i < x) {
13
+    arr.push(undefined)
14
+  }
15
+
16
+  return arr
17
+}
18
+
19
+export default {
20
+  name: 'VLine',
21
+  props: {
22
+    options: Object,
23
+    labels: Array,
24
+    num: {
25
+      type: Number,
26
+      default: 1,
27
+    }
28
+  },
29
+  components: {
30
+    'v-chart': ECharts,
31
+  },
32
+  data() {
33
+    return {
34
+      defaultOpts: {
35
+        legend: {},
36
+        tooltip: {},
37
+        xAxis: {},
38
+        yAxis: {},
39
+      }
40
+    };
41
+  },
42
+  computed: {
43
+    opts() {
44
+      let series = (this.labels || []).map((it, inx) => {
45
+        return {
46
+          type: 'line',
47
+          name: it,
48
+        }
49
+      })
50
+
51
+      if (!series || !series.length) {
52
+        series = times(this.num).map(() => ({ type: 'line' }))
53
+      }
54
+
55
+      return {
56
+        ...this.defaultOpts,
57
+        series,
58
+        ...(this.options || {}),
59
+      }
60
+    }
61
+  }
62
+}
63
+</script>

+ 18
- 0
src/views/indexEcharts/components/style.scss View File

@@ -0,0 +1,18 @@
1
+.chart-box {
2
+  background-color: #fff;
3
+  padding: 16px;
4
+
5
+  h1,h2,h3,h4,h5 {
6
+    margin: 0;
7
+  }
8
+  
9
+  small {
10
+    color: #666;
11
+    font-weight: 400;
12
+  }
13
+
14
+  .chart {
15
+    width: 100% !important;
16
+    // height: 100%;
17
+  }
18
+}

+ 32
- 507
src/views/indexEcharts/index.vue View File

@@ -11,51 +11,24 @@
11 11
       <card label="最近7天新增" @click="toNewUsers()" class="under-line" >{{echartsInfo.selectRecentlyCount}}</card>
12 12
     </el-col>
13 13
   </el-row>
14
-  <p class="title under-line" @click="toUserSource()">用户来源</p>
15
-  <span class="title-desc under-line" @click="toUserSource()">最近7天</span>
16
-  <el-row :gutter="20" :style="{ height: '560px',margin:'20px 0',border:'1px solid #eee',borderRadius:'5px'}">
17
-    <el-col :span="14">
18
-      <div class="grid-content" ref="firstChart"  id="firstChart"  :style="{ height: '500px' ,padding:'20px 10px'}" >
19
-      </div>
20
-    </el-col>
21
-    <el-col :span="10" :style="{ height: '560px',borderLeft:'1px solid #eee'}">
22
-      <div class="grid-content" ref="secondChart"  id="secondChart"  :style="{ height: '500px',padding:'20px 10px'}" >
23
-      </div>
24
-    </el-col>
25
-  </el-row>
26
-  <p class="title under-line" @click="toBehaviorAnalysis()">用户行为</p>
27
-  <span class="title-desc under-line" @click="toBehaviorAnalysis()">最近7天</span>
28
-  <!-- <div class="grid-content" ref="thirdChart"  id="thirdChart"  :style="{ height: '500px',margin:'20px 0',border:'1px solid #eee', padding:'20px',borderRadius:'5px'}" ></div> -->
29
-   <x-line :style="{height: '500px',margin:'20px 0',border:'1px solid #eee', padding:'20px',borderRadius:'5px'}"  :value="lineSeting"></x-line>
14
+  <user-source :value="userSourceData"></user-source>
15
+  <user-behavior class="marginTB" :value="userBehaviorData" @click="toBehaviorAnalysis()"></user-behavior>
30 16
  <el-row :gutter="20">
31 17
     <el-col :span="12">
32
-      <div class="grid-content" ref="fourthChart"  id="fourthChart"  :style="{height: '500px',margin:'20px 0',border:'1px solid #eee', padding:'20px',borderRadius:'5px'}" ></div>
18
+      <user-active :value="userActiveData"></user-active>
33 19
     </el-col>
34 20
     <el-col :span="12">
35
-      <div class="grid-content" ref="fifthChart"  id="fifthChart"  :style="{ height: '500px',margin:'20px 0',border:'1px solid #eee', padding:'20px',borderRadius:'5px'}" >
36
-      </div>
21
+      <user-conversion></user-conversion>
37 22
     </el-col>
38 23
     <el-col :span="12">
39
-      <div class="grid-content" ref="sixthChart"  id="sixthChart" :style="{ height: '500px',margin:'20px 0',border:'1px solid #eee', padding:'20px',borderRadius:'5px'}" >
40
-      </div>
24
+      <user-sex :value="userSexData"></user-sex>
41 25
     </el-col>
42 26
     <el-col :span="12">
43
-      <div class="grid-content" ref="seventhChart"  id="seventhChart" :style="{ height: '500px',margin:'20px 0',border:'1px solid #eee', padding:'20px',borderRadius:'5px'}" >
44
-      </div>
27
+      <user-city :value="userCityData"></user-city>
45 28
     </el-col>
46 29
   </el-row>
47
-  <p class="title under-line" @click="toNewUsers()">新增用户</p>
48
-  <span class="title-desc under-line" @click="toNewUsers()">最近7天</span>
49
-  <el-table :data="tableData"  border  center  style="width: 100%">
50
-    <el-table-column v-for="(item, index) in tableTitle" :key="index" :label="item" :prop="index == 0 ? 'label': item"></el-table-column>
51
-  </el-table>
52
-  <p class="title">意向客户</p>
53
-  <el-table :data="tableData2"  border  center  style="width: 100%">
54
-    <el-table-column label="用户姓名" prop="name"></el-table-column>
55
-    <el-table-column label="手机号" prop="phone"></el-table-column>
56
-    <el-table-column label="意向楼盘" prop="building"></el-table-column>
57
-    <el-table-column label="意向值" prop="num"></el-table-column>
58
-  </el-table>
30
+  <new-users class="marginTB" :value="newUserData"></new-users>
31
+  <intentional-customers  class="marginTB"></intentional-customers>
59 32
 </div>
60 33
 </template>
61 34
 
@@ -71,32 +44,24 @@ const {
71 44
 
72 45
 export default {
73 46
   components: {
74
-    XLine: () => import('@/components/charts/XLine.vue'),
75 47
     Card: () => import('./components/Card'),
48
+    UserSource: () => import('./components/UsrSRCLineAndPie'),
49
+    UserBehavior: () => import('./components/UserBehavior'),
50
+    UserActive: () => import('./components/UserActive'),
51
+    UserConversion: () => import('./components/UserConversion'),
52
+    UserSex: () => import('./components/UserSex'),
53
+    UserCity: () => import('./components/UserCity'),
54
+    NewUsers: () => import('./components/NewUsers'),
55
+    IntentionalCustomers: () => import('./components/IntentionalCustomers'),
76 56
   },
77 57
   data() {
78 58
     return {
79
-      // 新增用户
80
-      tableData: [
81
-        { label: '新增用户', },
82
-        { label: '授权注册', }
83
-      ],
84
-      tableTitle: [ '类型' ],
85
-      tableData2: [ ],
86
-      userBehavior: [], // 用户行为
87
-      lineSeting: {
88
-        dataset: {
89
-          dimensions: ['date', 'activity', 'activityCount'],
90
-          source: [],
91
-        },
92
-      },
93
-        // ----  用户来源 start -----
94
-        pieSecondChart: '', // 饼状图实例
95
-        columnarSecondChart: '', // 柱状图实例
96
-        // ----  用户来源 end -----
97
-        // ---- 性别 start ----
98
-        sexSixthChart: '', // 饼状图实例
99
-        // ---- 性别 end ------
59
+      userSourceData: {},
60
+      userBehaviorData: [],
61
+      userActiveData: [],
62
+      userSexData: [],
63
+      userCityData: [],
64
+      newUserData: [],
100 65
     };
101 66
   },
102 67
   computed: {
@@ -109,35 +74,11 @@ export default {
109 74
     initPage() {
110 75
       this.setDetailNull();
111 76
       this.getIndexEcharts().then(x => {
112
-        this.lineSeting.dataset.source = this.echartsInfo.selectUserBehavior
113
-        const data = this.echartsInfo.selectNewsUserCount
114
-        this.tableData = (data || []).reduce((acc, item, index) => {
115
-          const { date, userCount, authorizationCount } = item
116
-          const row2 = {
117
-            ...acc[0],
118
-            [`${date}`]: userCount,
119
-          }
120
-          const row3 = {
121
-            ...acc[1],
122
-            [`${date}`]: authorizationCount,
123
-          }
124
-
125
-          this.tableTitle = this.tableTitle.concat(`${date}`)
126
-
127
-          return [row2, row3];          
128
-        }, this.tableData)
129
-
130
-
131
-        // ----- 用户来源 start  -----
132
-          console.log('selectUserSource - pie: ', x.selectUserSource.pie)
133
-          console.log('selectUserSource - columnar: ', x.selectUserSource.columnar)
134
-          this.selectUserSourcePie(x.selectUserSource.pie)
135
-          this.selectUserSourceColumnar(x.selectUserSource.columnar)
136
-        // ----- 用户来源 end --------
137
-
138
-          // 用户性别
139
-          this.sexSixthChartPie(x.selectSexUser)
140
-
77
+        this.userSourceData = x.selectUserSource
78
+        this.userBehaviorData = x.selectUserBehavior
79
+        this.userActiveData = x.selectActiveUserCount
80
+        this.userSexData = x.selectSexUser
81
+        this.newUserData = this.echartsInfo.selectNewsUserCount
141 82
       });;
142 83
     },
143 84
     toNewUsers() {
@@ -149,429 +90,8 @@ export default {
149 90
     toBehaviorAnalysis() {
150 91
       this.$router.push({ name: "behaviorAnalysis" });
151 92
     },
152
-    drawLine() {
153
-        // --- 用户来源 start -------
154
-        // 柱状
155
-        this.columnarSecondChart = Echarts.init(this.$refs.firstChart);
156
-        // 饼图
157
-        this.pieSecondChart = Echarts.init(this.$refs.secondChart);
158
-        // --- 用户来源 start -------
159
-
160
-        // --- 性别 环形图 start -------
161
-        this.sexSixthChart = Echarts.init(this.$refs.sixthChart);
162
-        // --- 性别 环形图 end -------
163
-
164
-
165
-      // 折线图
166
-      // let thirdChart = Echarts.init(this.$refs.thirdChart);
167
-      // 绘制图表
168
-      // thirdChart.setOption({
169
-      //   title: {
170
-      //     text: "访问人数"
171
-      //   },
172
-      //   color: ["#ed3a3d", "#e613d2", "#2ed9f7", "#0ab662", "#165cf8", "#8854b9"],
173
-      //   tooltip: {
174
-      //     trigger: "axis"
175
-      //   },
176
-      //   legend: {
177
-      //     data: ["首页", "项目", "咨询", "名片", "活动", "资讯"]
178
-      //   },
179
-      //   grid: {
180
-      //     left: "3%",
181
-      //     right: "4%",
182
-      //     bottom: "3%",
183
-      //     containLabel: true
184
-      //   },
185
-      //   toolbox: {},
186
-      //   xAxis: {
187
-      //     type: "category",
188
-      //     boundaryGap: false,
189
-      //     data: ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]
190
-      //   },
191
-      //   yAxis: {
192
-      //     type: "value"
193
-      //   },
194
-      //   series: [
195
-      //     {
196
-      //       name: "首页",
197
-      //       type: "line",
198
-      //       stack: "1",
199
-      //       data: []
200
-      //     },
201
-      //     {
202
-      //       name: "项目",
203
-      //       type: "line",
204
-      //       stack: "2",
205
-      //       data: [220, 182, 191, 234, 290, 330, 310]
206
-      //     },
207
-      //     {
208
-      //       name: "咨询",
209
-      //       type: "line",
210
-      //       stack: "3",
211
-      //       data: [150, 232, 201, 154, 190, 330, 410]
212
-      //     },
213
-      //     {
214
-      //       name: "名片",
215
-      //       type: "line",
216
-      //       stack: "4",
217
-      //       data: [320, 332, 301, 334, 390, 330, 320]
218
-      //     },
219
-      //     {
220
-      //       name: "活动",
221
-      //       type: "line",
222
-      //       stack: "5",
223
-      //       data: [820, 932, 901, 544, 1290, 1330, 1320]
224
-      //     },
225
-      //     {
226
-      //       name: "资讯",
227
-      //       type: "line",
228
-      //       stack: "6",
229
-      //       data: [400, 500, 201, 934, 1290, 1423, 777]
230
-      //     }
231
-      //   ]
232
-      // });
233
-      // 柱状图
234
-      let fourthChart = Echarts.init(this.$refs.fourthChart);
235
-      // 绘制图表
236
-      let labelOption2 = {
237
-        normal: {
238
-          show: true,
239
-          position: "top",
240
-          fontSize: 15,
241
-          rich: {
242
-            name: {
243
-              textBorderColor: "#fff"
244
-            }
245
-          }
246
-        }
247
-      };
248
-      fourthChart.setOption({
249
-        title: {
250
-          text: "活跃用户数"
251
-        },
252
-        color: ["#7571cf"],
253
-        tooltip: {
254
-          trigger: "axis",
255
-          axisPointer: {
256
-            type: "shadow"
257
-          }
258
-        },
259
-        grid: {
260
-          left: "3%",
261
-          right: "4%",
262
-          bottom: "3%",
263
-          containLabel: true
264
-        },
265
-        xAxis: [
266
-          {
267
-            type: "category",
268
-            data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
269
-            axisTick: {
270
-              alignWithLabel: true
271
-            }
272
-          }
273
-        ],
274
-        yAxis: [
275
-          {
276
-            type: "value"
277
-          }
278
-        ],
279
-        series: [
280
-          {
281
-            name: "直接访问",
282
-            type: "bar",
283
-            barWidth: "60%",
284
-            label: labelOption2,
285
-            data: [10, 52, 200, 334, 390, 330, 220]
286
-          }
287
-        ]
288
-      });
289
-      // 环形图
290
-      let fifthChart = Echarts.init(this.$refs.fifthChart);
291
-      // 绘制图表
292
-      fifthChart.setOption({
293
-        title: {
294
-          text: "转化率"
295
-        },
296
-        color:["#6a96f7","#f5749d"],
297
-        tooltip: {
298
-          trigger: "item",
299
-          formatter: "{a} <br/>{b}: {c} ({d}%)"
300
-        },
301
-        legend: {
302
-          orient: "vertical",
303
-          x: "right",
304
-          data: ["收藏楼盘", "查看楼盘"]
305
-        },
306
-        series: [
307
-          {
308
-            name: "转化率",
309
-            type: "pie",
310
-            radius: ["40%", "56%"],
311
-            avoidLabelOverlap: false,
312
-            label: {
313
-              normal: {
314
-                show: false,
315
-                position: "center"
316
-              },
317
-              emphasis: {
318
-                show: true,
319
-                textStyle: {
320
-                  fontSize: "30",
321
-                  fontWeight: "bold"
322
-                }
323
-              }
324
-            },
325
-            data: [
326
-              { value: 335, name: "收藏楼盘" },
327
-              { value: 310, name: "查看楼盘" }
328
-            ]
329
-          }
330
-        ]
331
-      });
332
-
333
-      // 饼图
334
-      let seventhChart = Echarts.init(this.$refs.seventhChart);
335
-      // 绘制图表
336
-      seventhChart.setOption({
337
-        title: {
338
-          text: "城市分布"
339
-        },
340
-        tooltip: {
341
-          trigger: "item",
342
-          formatter: "{a} <br/>{b} : {c} ({d}%)"
343
-        },
344
-        legend: {
345
-          orient: "vertical",
346
-          left: "right",
347
-          data: ["合肥", "南京", "南通"]
348
-        },
349
-        series: [
350
-          {
351
-            name: "城市分布",
352
-            type: "pie",
353
-            radius: "55%",
354
-            center: ["50%", "60%"],
355
-            // label: {
356
-            //   normal: {
357
-            //     position: "inner"
358
-            //   }
359
-            // },
360
-            data: [
361
-              { value: 21, name: "合肥" },
362
-              { value: 90, name: "南京" },
363
-              { value: 47, name: "南通" }
364
-            ],
365
-            itemStyle: {
366
-              emphasis: {
367
-                shadowBlur: 10,
368
-                shadowOffsetX: 0,
369
-                shadowColor: "rgba(0, 0, 0, 0.5)"
370
-              }
371
-            }
372
-          }
373
-        ]
374
-      });
375
-    },
376
-      // ---------- 用户来源 start --------------
377
-      selectUserSourcePie (obj) { // 饼状图绘制
378
-          // 绘制图表
379
-          this.pieSecondChart.setOption({
380
-              color: ["#7974ce","#f5749d","#3688f8"],
381
-              tooltip: {
382
-                  trigger: "item",
383
-                  formatter: "{a} <br/>{b} : {c} ({d}%)"
384
-              },
385
-              legend: {
386
-                  orient: "vertical",
387
-                  left: "left",
388
-                  data: ["自主进入", "来源全民经纪人", "来源置业顾问"]
389
-              },
390
-              series: [
391
-                  {
392
-                      name: "访问来源",
393
-                      type: "pie",
394
-                      radius: "55%",
395
-                      center: ["50%", "60%"],
396
-                      // label: {
397
-                      //     normal: {
398
-                      //         position: "inner"
399
-                      //     }
400
-                      // },
401
-                      data: [
402
-                          { value: obj.person_null, name: "自主进入" },
403
-                          { value: obj.person_estate_agent, name: "来源全民经纪人" },
404
-                          { value: obj.person_realty_consultant, name: "来源置业顾问" }
405
-                      ],
406
-                      itemStyle: {
407
-                          emphasis: {
408
-                              shadowBlur: 10,
409
-                              shadowOffsetX: 0,
410
-                              shadowColor: "rgba(0, 0, 0, 0.5)"
411
-                          }
412
-                      }
413
-                  }
414
-              ]
415
-          });
416
-      },
417
-      selectUserSourceColumnar(obj) { // 柱状图
418
-          // 活动名称
419
-          const fromName = []
420
-
421
-          // 注册人数
422
-          const registered = []
423
-
424
-          // 注册人数
425
-          const userCount = []
426
-
427
-          obj.map((item, index) => {
428
-              fromName.push(item.fromName)
429
-              registered.push(item.registered)
430
-              userCount.push(item.userCount)
431
-          })
432
-
433
-          let labelOption = {
434
-              normal: {
435
-                  show: true,
436
-                  position: "top",
437
-                  fontSize: 15,
438
-                  rich: {
439
-                      name: {
440
-                          textBorderColor: "#fff"
441
-                      }
442
-                  }
443
-              }
444
-          };
445
-          // 绘制图表
446
-          this.columnarSecondChart.setOption({
447
-              color: ["#3688f8", "#7974ce"],
448
-              backgroundColor: "#fff",
449
-              tooltip: {
450
-                  trigger: "axis"
451
-              },
452
-              toolbox: {
453
-                  show: false,
454
-                  feature: {
455
-                      mark: { show: true },
456
-                      dataView: { show: true, readOnly: false },
457
-                      magicType: { show: true, type: ["bar"] },
458
-                      restore: { show: true },
459
-                      saveAsImage: { show: true }
460
-                  }
461
-              },
462
-              calculable: true,
463
-              legend: {
464
-                  data: ["所有用户", "注册用户"]
465
-              },
466
-              xAxis: [
467
-                  {
468
-                      type: "category",
469
-                      axisLabel: {
470
-                          interval: 0,
471
-                          formatter: function(val) {
472
-                              // return val.split("").join("\n");
473
-                              return val;
474
-                          }
475
-                      },
476
-                      // data: ["生成海报", "好友分享", "群分享", "线下扫码", "名片分享", "小程序搜索"]
477
-                      data: fromName
478
-                  }
479
-              ],
480
-              yAxis: [
481
-                  {
482
-                      type: "value",
483
-                      name: "人数(人)",
484
-                      axisTick: {
485
-                          inside: true
486
-                      },
487
-                      axisLabel: {
488
-                          formatter: "{value}"
489
-                      }
490
-                  }
491
-              ],
492
-              grid: {
493
-                  left: "1%",
494
-                  right: "1%",
495
-                  containLabel: true,
496
-                  y2: 10
497
-              },
498
-              series: [
499
-                  {
500
-                      name: "所有用户",
501
-                      type: "bar",
502
-                      smooth: true,
503
-                      label: labelOption,
504
-                      // data: [78, 90, 13, 81, 170, 77]
505
-                      data: registered
506
-                  },
507
-                  {
508
-                      name: "注册用户",
509
-                      type: "bar",
510
-                      smooth: true,
511
-                      label: labelOption,
512
-                      // data: [26, 49, 62, 45, 21, 89]
513
-                      data: userCount
514
-                  }
515
-              ]
516
-          });
517
-      },
518
-      // ---------- 用户来源 end -------------
519
-      // ---------- 性别 start --------------
520
-      sexSixthChartPie(obj) {
521
-          // 性别 绘制图表
522
-          this.sexSixthChart.setOption({
523
-              title: {
524
-                  text: "性别比例"
525
-              },
526
-              color:["#6a96f7","#f5749d"],
527
-              tooltip: {
528
-                  trigger: "item",
529
-                  formatter: "{a} <br/>{b}: {c} ({d}%)"
530
-              },
531
-              legend: {
532
-                  orient: "vertical",
533
-                  x: "right",
534
-                  data: ["男", "女"]
535
-              },
536
-              series: [
537
-                  {
538
-                      name: "性别比例",
539
-                      type: "pie",
540
-                      radius: ["40%", "56%"],
541
-                      avoidLabelOverlap: false,
542
-                      label: {
543
-                          normal: {
544
-                              show: false,
545
-                              position: "center"
546
-                          },
547
-                          emphasis: {
548
-                              show: true,
549
-                              textStyle: {
550
-                                  fontSize: "30",
551
-                                  fontWeight: "bold"
552
-                              }
553
-                          }
554
-                      },
555
-                      labelLine: {
556
-                          normal: {
557
-                              show: false
558
-                          }
559
-                      },
560
-                      // data: [{ value: 335, name: "男" }, { value: 310, name: "女" }]
561
-                      data: obj
562
-                  }
563
-              ]
564
-          });
565
-      }
566
-      // ---------- 性别 end ---------------
567 93
   },
568 94
   mounted() {
569
-    if (this.echartsInfo) {
570
-      this.drawLine();
571
-      // for (var i = 0; i < this.echartsInfo.selectUserBehavior.length; i++) {
572
-      //   this.members.push(this.echartsInfo.selectUserBehavior[i].members);
573
-      // }
574
-    }
575 95
     this.initPage();
576 96
   }
577 97
 };
@@ -585,6 +105,11 @@ export default {
585 105
 p {
586 106
   margin: 0;
587 107
 }
108
+
109
+.marginTB {
110
+  margin: 20px 0;
111
+}
112
+
588 113
 .top-info {
589 114
   margin: 20px 0;
590 115
   .grid-content {

+ 1
- 1
vue.config.js View File

@@ -4,7 +4,7 @@ module.exports = {
4 4
     port: 8080,
5 5
     proxy: {
6 6
       '/api': {
7
-        target: 'http://192.168.0.11:8080',
7
+        target: 'http://192.168.0.11:8566',
8 8
         // target: 'http://localhost:8080',
9 9
         changeOrigin: true,
10 10
         // pathRewrite: {