张延森 4 gadus atpakaļ
vecāks
revīzija
29b8822d2f

+ 2
- 2
config/routes.js Parādīt failu

201
                     path: '/report/post',
201
                     path: '/report/post',
202
                     name: '科普统计',
202
                     name: '科普统计',
203
                     menuCode: 'report.post',
203
                     menuCode: 'report.post',
204
-                    component: '../layouts/BlankLayout',
204
+                    component: './Statistic/PostData',
205
                   },
205
                   },
206
                   {
206
                   {
207
                     path: '/report/student',
207
                     path: '/report/student',
208
                     name: '阅读统计',
208
                     name: '阅读统计',
209
                     menuCode: 'report.student',
209
                     menuCode: 'report.student',
210
-                    component: '../layouts/BlankLayout',
210
+                    component: './Statistic/StudentData',
211
                   },
211
                   },
212
                 ],
212
                 ],
213
               },
213
               },

+ 1
- 2
src/components/ECharts/echarts.js Parādīt failu

4
 // 引入柱状图图表,图表后缀都为 Chart
4
 // 引入柱状图图表,图表后缀都为 Chart
5
 import {
5
 import {
6
   LineChart,
6
   LineChart,
7
-  BarChart
8
 } from 'echarts/charts';
7
 } from 'echarts/charts';
9
 // 引入提示框,标题,直角坐标系组件,组件后缀都为 Component
8
 // 引入提示框,标题,直角坐标系组件,组件后缀都为 Component
10
 import {
9
 import {
18
 
17
 
19
 // 注册必须的组件
18
 // 注册必须的组件
20
 echarts.use(
19
 echarts.use(
21
-  [CanvasRenderer, TitleComponent, TooltipComponent, GridComponent, BarChart, LineChart]
20
+  [CanvasRenderer, TitleComponent, TooltipComponent, GridComponent, LineChart]
22
 );
21
 );
23
 
22
 
24
 export default echarts;
23
 export default echarts;

+ 126
- 0
src/pages/Statistic/PostData.jsx Parādīt failu

1
+import React, { useEffect, useMemo, useRef } from 'react';
2
+import { connect } from 'umi';
3
+import moment from 'moment';
4
+import { PageContainer } from '@ant-design/pro-layout';
5
+import ProTable from '@ant-design/pro-table';
6
+import { queryTable } from '@/utils/request';
7
+
8
+const PostData = (props) => {
9
+  const tableRef = useRef()
10
+
11
+  const changeQueryParam = (params) => {
12
+    const dt = params.date
13
+    const startDate = dt ? dt[0] : undefined
14
+    const endDate = dt ? dt[1] : undefined
15
+
16
+    return {
17
+      ...params,
18
+      startDate: startDate ? moment(startDate).format('YYYY-MM-DD') : undefined,
19
+      endDate: endDate ? moment(endDate).format('YYYY-MM-DD') : undefined,
20
+      date: undefined,
21
+    }
22
+  }
23
+
24
+  const typeDict = useMemo(() => {
25
+    return (props.typeList || []).reduce((acc, item) => {
26
+      return {
27
+        ...acc,
28
+        [item.typeId]: { text: item.name },
29
+      };
30
+    }, {});
31
+  }, [props.typeList]);
32
+
33
+  const columns = [
34
+    {
35
+      title: '日期',
36
+      key: 'date',
37
+      hideInTable: true,
38
+      valueType: 'dateRange',
39
+    },
40
+    {
41
+      title: '名称',
42
+      key: 'name',
43
+      hideInTable: true,
44
+    },
45
+    {
46
+      title: '排名',
47
+      key: 'topN',
48
+      hideInSearch: true,
49
+      render: (_, $, index) => index + 1,
50
+    },
51
+    {
52
+      title: '科普知识',
53
+      key: 'postId',
54
+      dataIndex: 'postId',
55
+      hideInSearch: true,
56
+      render: (_, row) => (
57
+        <div>
58
+          <h3>{row.name}</h3>
59
+          <p>
60
+            <small>{`作者: ${row.author}`}</small>
61
+          </p>
62
+          <p>
63
+            <small>{row.isVideo ? '视频' : '图文'}</small>
64
+          </p>
65
+        </div>
66
+      ),
67
+    },
68
+    {
69
+      title: '分类',
70
+      key: 'typeId',
71
+      dataIndex: 'typeId',
72
+      valueType: 'select',
73
+      valueEnum: typeDict,
74
+    },
75
+    {
76
+      title: '阅读人数',
77
+      key: 'uv',
78
+      dataIndex: 'uv',
79
+      hideInSearch: true,
80
+      sorter: true,
81
+    },
82
+    {
83
+      title: '浏览量',
84
+      key: 'pv',
85
+      dataIndex: 'pv',
86
+      hideInSearch: true,
87
+      sorter: true,
88
+    },
89
+    {
90
+      title: '收藏量',
91
+      key: 'savedNum',
92
+      dataIndex: 'savedNum',
93
+      hideInSearch: true,
94
+      sorter: true,
95
+    },
96
+  ];
97
+
98
+  useEffect(() => {
99
+    if (!props.typeList || !props.typeList.length) {
100
+      props.dispatch({
101
+        type: 'post/getTypeList',
102
+        payload: { pageSize: 999 },
103
+      });
104
+    }
105
+  }, [props]);
106
+
107
+  return (
108
+    <PageContainer>
109
+      <ProTable
110
+        actionRef={tableRef}
111
+        columns={columns}
112
+        request={queryTable('/statis/post-data')}
113
+        rowKey="postId"
114
+        search={{
115
+          labelWidth: '4em',
116
+        }}
117
+        options={false}
118
+        beforeSearchSubmit={changeQueryParam}
119
+      />
120
+    </PageContainer>
121
+  );
122
+};
123
+
124
+export default connect((s) => ({
125
+  typeList: s.post.typeList,
126
+}))(PostData);

+ 102
- 0
src/pages/Statistic/StudentData.jsx Parādīt failu

1
+import React, { useEffect, useMemo, useRef, useState } from 'react';
2
+import { connect } from 'umi';
3
+import { PageContainer } from '@ant-design/pro-layout';
4
+import ProTable from '@ant-design/pro-table';
5
+import request, { queryTable } from '@/utils/request';
6
+
7
+const StudentData = (props) => {
8
+  const tableRef = useRef()
9
+  const [schoolDict, setSchoolDict] = useState({})
10
+
11
+  const columns = useMemo(() => [
12
+    {
13
+      title: '排名',
14
+      key: 'topN',
15
+      hideInSearch: true,
16
+      render: (_, $, index) => index + 1,
17
+    },
18
+    {
19
+      title: '学校',
20
+      key: 'schoolId',
21
+      dataIndex: 'schoolId',
22
+      valueType: 'select',
23
+      valueEnum: schoolDict,
24
+    },
25
+    {
26
+      title: '名称',
27
+      key: 'name',
28
+      dataIndex: 'name',
29
+    },
30
+    {
31
+      title: '手机号',
32
+      key: 'phone',
33
+      dataIndex: 'phone',
34
+      hideInSearch: true,
35
+    },
36
+    {
37
+      title: '收藏文章数',
38
+      key: 'savedNum',
39
+      dataIndex: 'savedNum',
40
+      hideInSearch: true,
41
+      sorter: true,
42
+    },
43
+    {
44
+      title: '阅读文章数',
45
+      key: 'readedNum',
46
+      dataIndex: 'readedNum',
47
+      hideInSearch: true,
48
+      sorter: true,
49
+    },
50
+    {
51
+      title: '总积分',
52
+      key: 'pointNum',
53
+      dataIndex: 'pointNum',
54
+      hideInSearch: true,
55
+      sorter: true,
56
+    },
57
+    {
58
+      title: '学分',
59
+      key: 'creditNum',
60
+      dataIndex: 'creditNum',
61
+      hideInSearch: true,
62
+      sorter: true,
63
+    },
64
+  ], [schoolDict])
65
+
66
+  useEffect(() => {
67
+    request('/school', { params: { pageSize: 500 } }).then(res => {
68
+      const records = res.records || []
69
+      const dict = records.reduce((acc, item) => {
70
+        return {
71
+          ...acc,
72
+          [item.schoolId]: { text: item.name },
73
+        };
74
+      }, {})
75
+      setSchoolDict(dict)
76
+    }).catch((e) => {
77
+      // eslint-disable-next-line
78
+      console.error(e.message)
79
+    })
80
+
81
+  // eslint-disable-next-line
82
+  }, [])
83
+
84
+  return (
85
+    <PageContainer>
86
+      <ProTable
87
+        actionRef={tableRef}
88
+        columns={columns}
89
+        request={queryTable('/statis/student-data')}
90
+        rowKey="personId"
91
+        search={{
92
+          labelWidth: '4em',
93
+        }}
94
+        options={false}
95
+      />
96
+    </PageContainer>
97
+  );
98
+};
99
+
100
+export default connect((s) => ({
101
+  user: s.user.currentUser,
102
+}))(StudentData);

+ 50
- 12
src/pages/Welcome/components/LineCard.jsx Parādīt failu

1
 import React, { useEffect, useRef, useState } from 'react'
1
 import React, { useEffect, useRef, useState } from 'react'
2
 import moment from 'moment';
2
 import moment from 'moment';
3
-import { Card, DatePicker } from 'antd';
3
+import { Button, Card, DatePicker, Space } from 'antd';
4
 import ECharts from '@/components/ECharts'
4
 import ECharts from '@/components/ECharts'
5
 import echarts from '@/components/ECharts/echarts'
5
 import echarts from '@/components/ECharts/echarts'
6
 import { assignOption } from '@/components/ECharts/utils'
6
 import { assignOption } from '@/components/ECharts/utils'
33
   }
33
   }
34
 }
34
 }
35
 
35
 
36
-const Condition = (props) => (
37
-  <DatePicker.RangePicker value={props.value} onChange={props.onChange}/>
38
-)
36
+const Condition = (props) => {
37
+  const [dtRange, setDtRange] = useState()
38
+
39
+  const handleWeek = () => {
40
+    setDtRange([
41
+      moment().startOf('week'),
42
+      moment(),
43
+    ])
44
+  }
45
+
46
+  const handleMonth = () => {
47
+    setDtRange([
48
+      moment().startOf('month'),
49
+      moment(),
50
+    ])
51
+  }
52
+
53
+  const handleChange = (vals) => {
54
+    setDtRange(vals)
55
+  }
56
+
57
+  useEffect(() => {
58
+    props.onChange(dtRange)
59
+  // eslint-disable-next-line react-hooks/exhaustive-deps
60
+  }, [dtRange])
61
+  
62
+  useEffect(() => {
63
+    // 默认本周
64
+    handleWeek()
65
+  // eslint-disable-next-line react-hooks/exhaustive-deps
66
+  }, [])
67
+
68
+
69
+  return (
70
+    <Space>
71
+      <Button onClick={handleMonth}>本月</Button>
72
+      <Button onClick={handleWeek}>本周</Button>
73
+      <DatePicker.RangePicker value={dtRange} onChange={handleChange}/>
74
+    </Space>
75
+  )
76
+}
39
 
77
 
40
 export default (props) => {
78
 export default (props) => {
41
   const chartRef = useRef()
79
   const chartRef = useRef()
42
   const [loading, setLoading] = useState(false)
80
   const [loading, setLoading] = useState(false)
43
   const [data, setData] = useState([])
81
   const [data, setData] = useState([])
44
   const [option, setOption] = useState(lineOption)
82
   const [option, setOption] = useState(lineOption)
45
-  const [dtRange, setDtRange] = useState([    
46
-    moment().subtract(30, 'days'),
47
-    moment(),
48
-  ])
83
+  const [dtRange, setDtRange] = useState()
49
   const [params, setParams] = useState()
84
   const [params, setParams] = useState()
50
 
85
 
51
   useEffect(() => {
86
   useEffect(() => {
52
-    setParams({
53
-      startDate: dtRange[0].format('YYYY-MM-DD'),      
54
-      endDate: dtRange[1].format('YYYY-MM-DD')
55
-    })
87
+    console.log('-------->', dtRange)
88
+    if (dtRange) {
89
+      setParams({
90
+        startDate: dtRange[0].format('YYYY-MM-DD'),      
91
+        endDate: dtRange[1].format('YYYY-MM-DD')
92
+      })
93
+    }
56
   }, [dtRange])
94
   }, [dtRange])
57
   
95
   
58
   useEffect(() => {
96
   useEffect(() => {

+ 9
- 1
src/utils/request.js Parādīt failu

91
 // 专门为 ProTable 定制的 request
91
 // 专门为 ProTable 定制的 request
92
 // https://procomponents.ant.design/components/table#request
92
 // https://procomponents.ant.design/components/table#request
93
 export const queryTable = (url) => {
93
 export const queryTable = (url) => {
94
-  return (params) => {
94
+  return (params, sort) => {
95
+    const sortKey = Object.keys(sort || {})[0]
96
+    const sortVal = sortKey ? sort[sortKey] : undefined
97
+    const asc = sortVal === 'ascend' ? { asc: sortKey } : {}
98
+    const desc = sortVal === 'descend' ? { desc: sortKey } : {}
99
+
95
     return new Promise((resolve) => {
100
     return new Promise((resolve) => {
96
       const { current, pageSize, ...leftParams } = params;
101
       const { current, pageSize, ...leftParams } = params;
102
+
97
       const options = {
103
       const options = {
98
         params: {
104
         params: {
99
           pageNum: current,
105
           pageNum: current,
100
           pageSize,
106
           pageSize,
107
+          ...asc,
108
+          ...desc,
101
           ...leftParams,
109
           ...leftParams,
102
         },
110
         },
103
       };
111
       };