张延森 4 年前
父节点
当前提交
edd8edff86

+ 21
- 21
config/routes.js 查看文件

195
                     menuCode: 'report.student',
195
                     menuCode: 'report.student',
196
                     component: './Statistic/StudentData',
196
                     component: './Statistic/StudentData',
197
                   },
197
                   },
198
-                  {
199
-                    path: '/report/student/saveNum',
200
-                    name: '收藏记录',
201
-                    menuCode: 'report.student',
202
-                    component: './Statistic/SaveNum',
203
-                    hideInMenu: true,
204
-                  },
205
-                  {
206
-                    path: '/report/student/readedNum',
207
-                    name: '阅读记录',
208
-                    menuCode: 'report.student',
209
-                    component: './Statistic/ReadedNum',
210
-                    hideInMenu: true,
211
-                  },
212
-                  {
213
-                    path: '/report/student/pointNum',
214
-                    name: '积分记录',
215
-                    menuCode: 'report.student',
216
-                    component: './Statistic/PointNum',
217
-                    hideInMenu: true,
218
-                  },
198
+                  // {
199
+                  //   path: '/report/student/saveNum',
200
+                  //   name: '收藏记录',
201
+                  //   menuCode: 'report.student',
202
+                  //   component: './Statistic/SaveNum',
203
+                  //   hideInMenu: true,
204
+                  // },
205
+                  // {
206
+                  //   path: '/report/student/readedNum',
207
+                  //   name: '阅读记录',
208
+                  //   menuCode: 'report.student',
209
+                  //   component: './Statistic/ReadedNum',
210
+                  //   hideInMenu: true,
211
+                  // },
212
+                  // {
213
+                  //   path: '/report/student/pointNum',
214
+                  //   name: '积分记录',
215
+                  //   menuCode: 'report.student',
216
+                  //   component: './Statistic/PointNum',
217
+                  //   hideInMenu: true,
218
+                  // },
219
                 ],
219
                 ],
220
               },
220
               },
221
               {
221
               {

+ 4
- 4
src/components/WangEditor/initEditor.js 查看文件

28
   editor.config.menus = [
28
   editor.config.menus = [
29
     'head', // 标题
29
     'head', // 标题
30
     'bold', // 粗体
30
     'bold', // 粗体
31
-    'fontSize', // 字号
32
-    'fontName', // 字体
31
+    // 'fontSize', // 字号
32
+    // 'fontName', // 字体
33
     'italic', // 斜体
33
     'italic', // 斜体
34
     'underline', // 下划线
34
     'underline', // 下划线
35
-    'strikeThrough', // 删除线
36
-    'foreColor', // 文字颜色
35
+    // 'strikeThrough', // 删除线
36
+    // 'foreColor', // 文字颜色
37
     'backColor', // 背景颜色
37
     'backColor', // 背景颜色
38
     'list', // 列表
38
     'list', // 列表
39
     'justify', // 对齐方式
39
     'justify', // 对齐方式

+ 0
- 53
src/pages/Statistic/PointNum.jsx 查看文件

1
-import React from 'react';
2
-import { connect, history } from 'umi';
3
-import { Button } from 'antd';
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 SaveNum = () => {
9
-
10
-  const columns = [
11
-    {
12
-      title: '科普名称',
13
-      key: 'name',
14
-      dataIndex: 'name',
15
-    },
16
-    {
17
-      title: '积分',
18
-      key: 'point',
19
-      dataIndex: 'point',
20
-    },
21
-    {
22
-      title: '获取时间',
23
-      key: 'date',
24
-      dataIndex: 'date',
25
-      valueType: 'dateTime',
26
-    },
27
-  ];
28
-
29
-  return (
30
-    <PageContainer
31
-      header={{
32
-        extra: [
33
-          <Button key="1" onClick={() => history.go('-1')}>
34
-            返回
35
-          </Button>,
36
-        ],
37
-      }}
38
-    >
39
-      <ProTable
40
-        toolbar={{
41
-          title:<div><span>{'姓名'}</span><span style={{marginLeft: '30vw'}}>总积分:{}</span></div>,
42
-        }}
43
-        columns={columns}
44
-        search={false}
45
-        // request={queryTable('/statis/student-data')}
46
-        rowKey="personId"
47
-        options={false}
48
-      />
49
-    </PageContainer>
50
-  );
51
-};
52
-
53
-export default SaveNum

+ 0
- 58
src/pages/Statistic/ReadedNum.jsx 查看文件

1
-import React  from 'react';
2
-import { connect, history } from 'umi';
3
-import { Button } from 'antd';
4
-import { PageContainer } from '@ant-design/pro-layout';
5
-import ProTable from '@ant-design/pro-table';
6
-import request, { queryTable } from '@/utils/request';
7
-
8
-const ReadedNum = () => {
9
-
10
-  const columns = [
11
-    {
12
-      title: '科普名称',
13
-      key: 'name',
14
-      dataIndex: 'name',
15
-    },
16
-    {
17
-      title: '阅读时长',
18
-      key: 'name1',
19
-      dataIndex: 'name1',
20
-    },
21
-    {
22
-      title: '阅读进度',
23
-      key: 'name2',
24
-      dataIndex: 'name2',
25
-    },
26
-    {
27
-      title: '最后时间',
28
-      key: 'date',
29
-      dataIndex: 'date',
30
-      valueType: 'dateTime',
31
-    },
32
-  ];
33
-
34
-  return (
35
-    <PageContainer
36
-      header={{
37
-        extra: [
38
-          <Button key="1" onClick={() => history.go('-1')}>
39
-            返回
40
-          </Button>,
41
-        ],
42
-      }}
43
-    >
44
-      <ProTable
45
-        toolbar={{
46
-          title:<div><span>姓名</span><span style={{marginLeft: '30vw'}}>阅读量</span></div>
47
-        }}
48
-        columns={columns}
49
-        search={false}
50
-        // request={queryTable('/statis/student-data')}
51
-        rowKey="personId"
52
-        options={false}
53
-      />
54
-    </PageContainer>
55
-  );
56
-};
57
-
58
-export default ReadedNum

+ 0
- 51
src/pages/Statistic/SaveNum.jsx 查看文件

1
-import React from 'react';
2
-import { connect, history } from 'umi';
3
-import { Button } from 'antd';
4
-import { PageContainer } from '@ant-design/pro-layout';
5
-import ProTable from '@ant-design/pro-table';
6
-import request, { queryTable } from '@/utils/request';
7
-
8
-const SaveNum = () => {
9
-
10
-
11
-  const columns = [
12
-    {
13
-      title: '科普名称',
14
-      key: 'name',
15
-      dataIndex: 'name',
16
-    },
17
-    {
18
-      title: '收藏时间',
19
-      key: 'date',
20
-      dataIndex: 'date',
21
-      valueType: 'dateTime',
22
-    },
23
-  ];
24
-
25
-
26
-  return (
27
-    <PageContainer
28
-      header={{
29
-        extra: [
30
-          <Button key="1" onClick={() => history.go('-1')}>
31
-            返回
32
-          </Button>,
33
-        ],
34
-      }}
35
-    >
36
-      <ProTable
37
-        toolbar={{
38
-          title:<div><span>{'姓名'}</span><span style={{marginLeft: '30vw'}}>收藏数:{}</span></div>,
39
-          
40
-        }}
41
-        columns={columns}
42
-        search={false}
43
-        // request={queryTable('/statis/student-data')}
44
-        rowKey="personId"
45
-        options={false}
46
-      />
47
-    </PageContainer>
48
-  );
49
-};
50
-
51
-export default SaveNum

+ 61
- 33
src/pages/Statistic/StudentData.jsx 查看文件

1
-import React, { useEffect, useMemo, useRef, useState } from 'react';
1
+import React, { useEffect, useRef, useState } from 'react';
2
 import { connect, history } from 'umi';
2
 import { connect, history } from 'umi';
3
-import {Space, Button} from 'antd'
3
+import {Space, Button, notification} from 'antd'
4
 import { PageContainer } from '@ant-design/pro-layout';
4
 import { PageContainer } from '@ant-design/pro-layout';
5
 import ProTable from '@ant-design/pro-table';
5
 import ProTable from '@ant-design/pro-table';
6
 import request, { queryTable } from '@/utils/request';
6
 import request, { queryTable } from '@/utils/request';
7
+import DetailDrawer from './components/DetailDrawer'
7
 
8
 
8
 const StudentData = (props) => {
9
 const StudentData = (props) => {
9
-  const { postId } = props.location.query;
10
+  // const { postId } = props.location.query;
11
+  const paramRef = useRef();
12
+  const [exporting, setExporting] = useState(false)
13
+  const [student, setStudent] = useState();
14
+  const [modalVisible, setModalVisible] = useState({
15
+    points: false,
16
+    saved: false,
17
+    readed: false,
18
+  })
19
+
20
+  const toggleModal = (modal, visible) => {
21
+    setModalVisible({
22
+      ...modalVisible,
23
+      [modal]: visible,
24
+    })
25
+  }
10
 
26
 
11
   const tableRef = useRef()
27
   const tableRef = useRef()
12
   const [schoolDict, setSchoolDict] = useState({})
28
   const [schoolDict, setSchoolDict] = useState({})
13
-  
14
-
15
-  const toSave =(row)=>{
16
 
29
 
30
+  const toSave = (row) =>{
31
+    setStudent(row);
17
     if(row.savedNum>0){
32
     if(row.savedNum>0){
18
-      history.push(`/report/student/savenum?schoolId=${row?.schoolId}&personId=${row.personId}`);
19
-     
20
-      
33
+      toggleModal('saved', true);
21
     }
34
     }
22
-
23
   }
35
   }
24
 
36
 
25
-  const toReade =(row)=>{
26
-
37
+  const toReade = (row) =>{
38
+    setStudent(row);
27
     if(row.readedNum>0){
39
     if(row.readedNum>0){
28
-      history.push(`/report/student/readednum?schoolId=${row?.schoolId}&personId=${row.personId}`);
40
+      toggleModal('readed', true);
29
     }
41
     }
30
-
31
   }
42
   }
32
-  const toPoint =(row)=>{
33
-
43
+  const toPoint = (row) =>{
44
+    setStudent(row);
34
     if(row.pointNum>0){
45
     if(row.pointNum>0){
35
-      history.push(`/report/student/pointnum?schoolId=${row?.schoolId}&personId=${row.personId}`);
46
+      toggleModal('points', true);
36
     }
47
     }
37
-
38
   }
48
   }
39
-  
40
-  const columns = useMemo(() => [
49
+
50
+  const columns = [
41
     {
51
     {
42
       title: '排名',
52
       title: '排名',
43
       key: 'topN',
53
       key: 'topN',
105
       hideInSearch: true,
115
       hideInSearch: true,
106
       sorter: true,
116
       sorter: true,
107
     },
117
     },
108
-  ], [schoolDict])
118
+  ]
119
+
120
+  const handleBeforeSearch = (params) => {
121
+    const paramData = {
122
+      name: params.name,
123
+      schoolId: params.schoolId,
124
+      specialtyId: params.specialtyId,
125
+    }
126
+
127
+    // copy 一份
128
+    paramRef.current = paramData
129
+    return params
130
+  }
131
+
132
+  const handleExport = () => {
133
+    setExporting(true)
134
+    request('/export/statis/student-data', { params: paramRef.current || {} }).then(() => {
135
+      setExporting(false)
136
+    }).catch((err) => {
137
+      setExporting(false)
138
+      notification.error({ message: err.message })
139
+    })
140
+  }
109
 
141
 
110
   useEffect(() => {
142
   useEffect(() => {
111
     request('/school', { params: { pageSize: 500 } }).then(res => {
143
     request('/school', { params: { pageSize: 500 } }).then(res => {
129
     <PageContainer
161
     <PageContainer
130
     header={{
162
     header={{
131
       extra: [
163
       extra: [
132
-        postId&&<Button key="1" onClick={() => history.go('-1')}>
164
+        <Button key="1" onClick={() => history.go('-1')}>
133
           返回
165
           返回
134
         </Button>,
166
         </Button>,
135
       ],
167
       ],
137
       <ProTable
169
       <ProTable
138
         actionRef={tableRef}
170
         actionRef={tableRef}
139
         columns={columns}
171
         columns={columns}
140
-        params={{postId}}
172
+        beforeSearchSubmit={handleBeforeSearch}
141
         request={queryTable('/statis/student-data')}
173
         request={queryTable('/statis/student-data')}
142
         rowKey="personId"
174
         rowKey="personId"
143
-        search={{
144
-          labelWidth: '4em',
145
-          defaultCollapsed: false,
146
-          optionRender: (searchConfig, formProps, dom) => [
147
-            ...dom.reverse(),
148
-            <Button key="out"  type="primary">导出</Button>,
149
-          ],
150
-        }}
151
-       
152
-        options={false}
175
+        search={{ labelWidth: '4em' }}
176
+        toolBarRender={() => [
177
+          <Button key="export" type="primary" loading={exporting} onClick={handleExport}>导出</Button>
178
+        ]}
153
       />
179
       />
180
+
181
+      <DetailDrawer student={student} visible={modalVisible} onClose={setModalVisible} />
154
     </PageContainer>
182
     </PageContainer>
155
   );
183
   );
156
 };
184
 };

+ 48
- 0
src/pages/Statistic/components/DetailDrawer.jsx 查看文件

1
+import React from 'react'
2
+import { Drawer } from 'antd'
3
+import PointNum from './PointNum'
4
+import ReadedNum from './ReadedNum'
5
+import SaveNum from './SaveNum'
6
+
7
+export default (props) => {
8
+  const toggleVisible = (target, visible) => {
9
+    props.onClose({
10
+      ...props.visible,
11
+      [target]: visible,
12
+    })
13
+  }
14
+
15
+  const custDrawerProp = {
16
+    placement: 'right',
17
+    width: '60vw',
18
+  }
19
+
20
+  return (
21
+    <>
22
+      <Drawer
23
+        title="积分记录"
24
+        visible={props.visible.points}
25
+        onClose={() => toggleVisible('points', false)}
26
+        {...custDrawerProp}
27
+      >
28
+        <PointNum personId={props.student?.personId} />
29
+      </Drawer>
30
+      <Drawer
31
+        title="阅读"
32
+        visible={props.visible.readed}
33
+        onClose={() => toggleVisible('readed', false)}
34
+        {...custDrawerProp}
35
+      >
36
+        <ReadedNum personId={props.student?.personId} />
37
+      </Drawer>
38
+      <Drawer
39
+        title="收藏"
40
+        visible={props.visible.saved}
41
+        onClose={() => toggleVisible('saved', false)}
42
+        {...custDrawerProp}
43
+      >
44
+        <SaveNum personId={props.student?.personId} />
45
+      </Drawer>
46
+    </>
47
+  )
48
+}

+ 74
- 0
src/pages/Statistic/components/PointNum.jsx 查看文件

1
+import React, { useEffect, useState } from 'react';
2
+import { connect, history } from 'umi';
3
+import { Row, Col, Card, Space, notification, Statistic } from 'antd';
4
+// import { PageContainer } from '@ant-design/pro-layout';
5
+import ProTable from '@ant-design/pro-table';
6
+// import ProCard from '@ant-design/pro-card';
7
+import request, { queryTable } from '@/utils/request';
8
+
9
+const SaveNum = (props) => {
10
+  const [person, setPerson] = useState()
11
+
12
+  const columns = [
13
+    {
14
+      title: '科普名称',
15
+      key: 'targetName',
16
+      dataIndex: 'targetName',
17
+    },
18
+    {
19
+      title: '积分',
20
+      key: 'pointsNum',
21
+      dataIndex: 'pointsNum',
22
+    },
23
+    {
24
+      title: '获取时间',
25
+      key: 'createDate',
26
+      dataIndex: 'createDate',
27
+      valueType: 'dateTime',
28
+    },
29
+  ];
30
+
31
+  useEffect(() => {
32
+    request(`/person/${props.personId}`).then(res => {
33
+      setPerson(res)
34
+    }).catch((err) => {
35
+      notification.error({ message: err.message })
36
+    })
37
+  }, [props.personId])
38
+
39
+  return (
40
+    // <PageContainer
41
+    //   header={{
42
+    //     extra: [
43
+    //       <Button key="1" onClick={() => history.go('-1')}>
44
+    //         返回
45
+    //       </Button>,
46
+    //     ],
47
+    //   }}
48
+    // >
49
+      <div>
50
+        <Card style={{marginBottom: '2em'}} bordered={false}>
51
+          <Row gutter={24}>
52
+            <Col span={12}>
53
+              <Statistic title="姓名" value={person?.nickName} />
54
+            </Col>
55
+            <Col span={12}>
56
+              <Statistic title="积分" value={person?.personData?.pointNum} />
57
+            </Col>
58
+          </Row>
59
+        </Card>
60
+
61
+        <ProTable
62
+          columns={columns}
63
+          search={false}
64
+          params={{ personId: props.personId }}
65
+          request={queryTable('/points-log')}
66
+          rowKey="serialNo"
67
+          options={false}
68
+        />
69
+      </div>
70
+    // </PageContainer>
71
+  );
72
+};
73
+
74
+export default SaveNum

+ 68
- 0
src/pages/Statistic/components/ReadedNum.jsx 查看文件

1
+import React, { useEffect, useState } from 'react';
2
+// import { connect, history } from 'umi';
3
+import { notification, Row, Col, Card, Statistic } from 'antd';
4
+// import { PageContainer } from '@ant-design/pro-layout';
5
+import ProTable from '@ant-design/pro-table';
6
+import request, { queryTable } from '@/utils/request';
7
+
8
+const ReadedNum = (props) => {
9
+  const [person, setPerson] = useState()
10
+
11
+  const columns = [
12
+    {
13
+      title: '科普名称',
14
+      key: 'postName',
15
+      dataIndex: 'postName',
16
+    },
17
+    {
18
+      title: '阅读时间',
19
+      key: 'createDate',
20
+      dataIndex: 'createDate',
21
+      valueType: 'dateTime',
22
+    },
23
+  ];
24
+
25
+  useEffect(() => {
26
+    request(`/person/${props.personId}`).then(res => {
27
+      setPerson(res)
28
+    }).catch((err) => {
29
+      notification.error({ message: err.message })
30
+    })
31
+  }, [props.personId])
32
+
33
+  return (
34
+    // <PageContainer
35
+    //   header={{
36
+    //     extra: [
37
+    //       <Button key="1" onClick={() => history.go('-1')}>
38
+    //         返回
39
+    //       </Button>,
40
+    //     ],
41
+    //   }}
42
+    // >
43
+    <div>
44
+      <Card style={{marginBottom: '2em'}} bordered={false}>
45
+        <Row gutter={24}>
46
+          <Col span={12}>
47
+            <Statistic title="姓名" value={person?.nickName} />
48
+          </Col>
49
+          <Col span={12}>
50
+            <Statistic title="阅读数" value={person?.personData?.readedNum} />
51
+          </Col>
52
+        </Row>
53
+      </Card>
54
+
55
+      <ProTable
56
+        columns={columns}
57
+        search={false}
58
+        params={{ personId: props.personId }}
59
+        request={queryTable('/read-log')}
60
+        rowKey="serialNo"
61
+        options={false}
62
+      />
63
+    </div>
64
+    // </PageContainer>
65
+  );
66
+};
67
+
68
+export default ReadedNum

+ 69
- 0
src/pages/Statistic/components/SaveNum.jsx 查看文件

1
+import React, {useEffect, useState} from 'react';
2
+// import { connect, history } from 'umi';
3
+import { notification, Row, Col, Card, Statistic } from 'antd';
4
+// import { PageContainer } from '@ant-design/pro-layout';
5
+import ProTable from '@ant-design/pro-table';
6
+import request, { queryTable } from '@/utils/request';
7
+
8
+const SaveNum = (props) => {
9
+  const [person, setPerson] = useState()
10
+
11
+  const columns = [
12
+    {
13
+      title: '科普名称',
14
+      key: 'name',
15
+      dataIndex: 'name',
16
+    },
17
+    {
18
+      title: '收藏时间',
19
+      key: 'savedDate',
20
+      dataIndex: 'savedDate',
21
+      valueType: 'dateTime',
22
+    },
23
+  ];
24
+
25
+  useEffect(() => {
26
+    request(`/person/${props.personId}`).then(res => {
27
+      setPerson(res)
28
+    }).catch((err) => {
29
+      notification.error({ message: err.message })
30
+    })
31
+  }, [props.personId])
32
+
33
+
34
+  return (
35
+    // <PageContainer
36
+    //   header={{
37
+    //     extra: [
38
+    //       <Button key="1" onClick={() => history.go('-1')}>
39
+    //         返回
40
+    //       </Button>,
41
+    //     ],
42
+    //   }}
43
+    // >
44
+    <div>
45
+      <Card style={{marginBottom: '2em'}} bordered={false}>
46
+        <Row gutter={24}>
47
+          <Col span={12}>
48
+            <Statistic title="姓名" value={person?.nickName} />
49
+          </Col>
50
+          <Col span={12}>
51
+            <Statistic title="收藏数" value={person?.personData?.savedNum} />
52
+          </Col>
53
+        </Row>
54
+      </Card>
55
+
56
+      <ProTable
57
+        columns={columns}
58
+        search={false}
59
+        params={{ personId: props.personId }}
60
+        request={queryTable('/post-save')}
61
+        rowKey="personId"
62
+        options={false}
63
+      />
64
+    </div>
65
+    // </PageContainer>
66
+  );
67
+};
68
+
69
+export default SaveNum

+ 8
- 0
src/utils/request.js 查看文件

1
 /** Request 网络请求工具 更详细的 api 文档: https://github.com/umijs/umi-request */
1
 /** Request 网络请求工具 更详细的 api 文档: https://github.com/umijs/umi-request */
2
 import { extend } from 'umi-request';
2
 import { extend } from 'umi-request';
3
 import { notification } from 'antd';
3
 import { notification } from 'antd';
4
+import { downloadFile } from './utils'
4
 
5
 
5
 const codeMessage = {
6
 const codeMessage = {
6
   200: '服务器成功返回请求的数据。',
7
   200: '服务器成功返回请求的数据。',
81
     }
82
     }
82
     return Promise.reject(result);
83
     return Promise.reject(result);
83
   }
84
   }
85
+  
86
+  if (contextType.indexOf('application/vnd.ms-excel') > -1) {
87
+    const data = await response.clone().blob();
88
+    const content = response.headers.get('content-disposition');
89
+    const fileName = content.replace('attachment;filename=', '')
90
+    downloadFile(data, decodeURIComponent(fileName))
91
+  }
84
 
92
 
85
   return response;
93
   return response;
86
 });
94
 });

+ 10
- 0
src/utils/utils.js 查看文件

45
 }
45
 }
46
 
46
 
47
 export const defaultAvatar = 'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png'
47
 export const defaultAvatar = 'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png'
48
+
49
+export function downloadFile(data, fileName) {
50
+  const url = window.URL.createObjectURL(new Blob([data]))
51
+  const link = document.createElement('a')
52
+  link.style.display = 'none'
53
+  link.href = url
54
+  link.setAttribute('download', fileName)
55
+  document.body.append(link)
56
+  link.click()
57
+}