瀏覽代碼

工作台

李志伟 3 年之前
父節點
當前提交
7d2d4e1dcf

+ 8
- 0
config/routes.js 查看文件

@@ -30,6 +30,14 @@ export default [
30 30
     icon: 'DashboardOutlined',
31 31
     component: './dashboard',
32 32
   },
33
+
34
+  {
35
+    path: '/orgDashboard',
36
+    name: '工作台',//企业管理员工作台
37
+    access: 'org',
38
+    icon: 'DashboardOutlined',
39
+    component: './orgDashboard',
40
+  },
33 41
   {
34 42
     path: '/',
35 43
     name: '工作台',//暂定

+ 4
- 1
src/components/echart/echart.jsx 查看文件

@@ -2,7 +2,7 @@ import React, { useEffect, useRef } from 'react'
2 2
 // 引入 echarts 核心模块,核心模块提供了 echarts 使用必须要的接口。
3 3
 import * as echarts from 'echarts/core';
4 4
 // 引入柱状图图表,图表后缀都为 Chart
5
-import { BarChart } from 'echarts/charts';
5
+import { BarChart, LineChart } from 'echarts/charts';
6 6
 // 引入提示框,标题,直角坐标系,数据集,内置数据转换器组件,组件后缀都为 Component
7 7
 import {
8 8
   TitleComponent,
@@ -11,6 +11,7 @@ import {
11 11
   DatasetComponent,
12 12
   TransformComponent,
13 13
   DataZoomComponent,
14
+  LegendComponent,
14 15
 } from 'echarts/components';
15 16
 // 标签自动布局,全局过渡动画等特性
16 17
 import { LabelLayout, UniversalTransition } from 'echarts/features';
@@ -21,11 +22,13 @@ import { CanvasRenderer } from 'echarts/renderers';
21 22
 echarts.use([
22 23
   TitleComponent,
23 24
   TooltipComponent,
25
+  LegendComponent,
24 26
   GridComponent,
25 27
   DatasetComponent,
26 28
   DataZoomComponent,
27 29
   TransformComponent,
28 30
   BarChart,
31
+  LineChart,//折线图
29 32
   LabelLayout,
30 33
   UniversalTransition,
31 34
   CanvasRenderer

+ 111
- 0
src/pages/orgDashboard/components/BannerStatis.jsx 查看文件

@@ -0,0 +1,111 @@
1
+import { useEffect, useState } from 'react';
2
+import { history } from 'umi';
3
+import { Card, Row, Col } from 'antd'
4
+import { AppstoreOutlined, MacCommandOutlined, TeamOutlined, UsergroupDeleteOutlined, UsergroupAddOutlined } from '@ant-design/icons'
5
+import { getOrgComm } from '@/services/statis';
6
+import StatisCard from './StatisCard';
7
+import StatisGroup from './StatisGroup';
8
+
9
+const colorList = [
10
+  { backColor: '#126BAE', frontColor: '#fff' },
11
+  { backColor: '#66A9C9', frontColor: '#fff' },
12
+  { backColor: '#08507b', frontColor: '#fff' },
13
+]
14
+
15
+export default (props) => {
16
+  const [cardData, setCardData] = useState({})
17
+
18
+  const toAbnormal = () => {
19
+    history.push('../resume-work/abnormal');
20
+  }
21
+
22
+  useEffect(() => {
23
+    getOrgComm().then((res) => {
24
+      setCardData(res || {});
25
+    })
26
+  }, [])
27
+
28
+  const abnormalNum = (cardData.todayReportNum || 0) - (cardData.todayNormalNum || 0)
29
+
30
+  return (
31
+    <Row justify='space-around' gutter={24} >
32
+      <Col span={8}>
33
+        <StatisGroup
34
+          title="企业"
35
+          data1={{ title: '历史提交总数', value: cardData.orgTotalNum || 0 }}
36
+          data2={{ title: ' ', value: -1 }}
37
+          {...colorList[0]}
38
+          icon={<AppstoreOutlined />}
39
+        />
40
+      </Col>
41
+      <Col span={8}>
42
+        <StatisGroup
43
+          title="上报人次"
44
+          data1={{ title: '今日提交', value: cardData.todayReportNum || 0 }}
45
+          data2={{ title: '昨日提交', value: cardData.yestodayReportNum || 0 }}
46
+          {...colorList[1]}
47
+          icon={<TeamOutlined />}
48
+        />
49
+      </Col>
50
+      <Col span={8}>
51
+        <StatisGroup
52
+          title="今日概况"
53
+          data1={{ title: '正常人次', value: cardData.todayNormalNum || 0 }}
54
+          data2={{ title: '异常人次', value: abnormalNum }}
55
+          {...colorList[2]}
56
+          icon={<UsergroupDeleteOutlined />}
57
+          onClick2={toAbnormal}
58
+        />
59
+      </Col>
60
+      {/* <Col span={4}>
61
+        <StatisCard
62
+          title="企业总数"
63
+          value={cardData?.orgTotalNum || 0}
64
+          icon={<AppstoreOutlined />}
65
+          {...colorList[0]}
66
+        />
67
+      </Col>
68
+      <Col span={4}>
69
+        <StatisCard
70
+          title="无数据企业"
71
+          value={`${cardData?.noDataOrgNum || 0} / ${cardData?.orgTotalNum || 0}`}
72
+          icon={<MacCommandOutlined />}
73
+          {...colorList[1]}
74
+        />
75
+      </Col>
76
+      <Col span={4}>
77
+        <StatisCard
78
+          title="今日提交总人数"
79
+          value={cardData?.todayReportNum || 0}
80
+          icon={<TeamOutlined />}
81
+          {...colorList[2]}
82
+        />
83
+      </Col>
84
+      <Col span={4}>
85
+        <StatisCard
86
+          title="昨日提交总人数"
87
+          value={cardData?.yestodayReportNum || 0}
88
+          icon={<TeamOutlined />}
89
+          {...colorList[3]}
90
+        />
91
+      </Col>
92
+      <Col span={4}>
93
+        <StatisCard
94
+          title="今日正常人数"
95
+          value={cardData?.todayNormalNum || 0}
96
+          icon={<UsergroupDeleteOutlined />}
97
+          {...colorList[4]}
98
+        />
99
+      </Col>
100
+      <Col span={4}>
101
+        <StatisCard
102
+          title="今日异常人数"
103
+          value={(cardData?.todayReportNum || 0) - (cardData?.todayNormalNum || 0)}
104
+          icon={<UsergroupAddOutlined />}
105
+          {...colorList[5]}
106
+          onClick={toAbnormal}
107
+        />
108
+      </Col> */}
109
+    </Row>
110
+  )
111
+}

+ 130
- 0
src/pages/orgDashboard/components/OrgSummary.jsx 查看文件

@@ -0,0 +1,130 @@
1
+import { useEffect, useState, useCallback } from 'react';
2
+import Echart from '@/components/echart/echart'
3
+import { Card } from 'antd'
4
+import { getAllOrgLine } from '@/services/statis'
5
+import { useModel } from 'umi'
6
+import moment from 'moment';
7
+
8
+const lineOption = {
9
+  tooltip: {
10
+    trigger: 'axis',
11
+    axisPointer: {
12
+      type: 'shadow'
13
+    },
14
+    // formatter: (params) => `截止:${params[0].data.name} <br />正常: ${params[0].data.value}`
15
+    // formatter: (params) => `人次: ${params[0].data.value || 0}`
16
+  },
17
+
18
+  grid: {
19
+    containLabel: true,
20
+    left: 0,
21
+    top: 8,
22
+    right: 60,
23
+    bottom: 0,
24
+  },
25
+  yAxis: {
26
+    type: 'value',
27
+  },
28
+
29
+  xAxis: {
30
+    type: 'category',
31
+
32
+  },
33
+
34
+
35
+  dataset: [
36
+    {
37
+      dimensions: ['name', 'value'],
38
+      source: [],
39
+    },
40
+    {
41
+      dimensions: ['name', 'value'],
42
+      source: [],
43
+    }
44
+  ],
45
+  series: [
46
+    {
47
+      name: '正常',
48
+      type: 'line',
49
+      datasetIndex: 0,
50
+      itemStyle: {
51
+        normal: {
52
+          color: "#08507b",
53
+          lineStyle: {
54
+            color: "#08507b"
55
+          }
56
+        }
57
+      }
58
+
59
+
60
+
61
+    },
62
+    {
63
+      name: '异常',
64
+      type: 'line',
65
+      datasetIndex: 1,
66
+      itemStyle: {
67
+        normal: {
68
+          color: "red",
69
+          lineStyle: {
70
+            color: "red"
71
+          }
72
+        }
73
+      }
74
+
75
+      // lineStyle: {
76
+      //   color: 'red',
77
+      // },
78
+    }
79
+  ]
80
+}
81
+
82
+
83
+export default (props) => {
84
+  const [loading, setLoading] = useState(false)
85
+  const [list, setList] = useState({})
86
+  const { initialState } = useModel('@@initialState');
87
+
88
+  const dataset = [
89
+    {
90
+      dimensions: ['name', 'value'],
91
+      source: list.normal || [],
92
+    },
93
+    {
94
+      dimensions: ['name', 'value'],
95
+      source: list.abnormal || [],
96
+    }
97
+  ]
98
+
99
+  const option = {
100
+    ...lineOption,
101
+    dataset,
102
+  }
103
+  console.log('dataset', dataset);
104
+
105
+
106
+  useEffect(() => {
107
+    // queryList()
108
+    setLoading(true)
109
+
110
+    getAllOrgLine({
111
+      days: 7,
112
+      startDate: moment().subtract(7, 'day').format('YYYY-MM-DD'),
113
+      orgId: initialState.currentUser.orgId,
114
+    }).then((res) => {
115
+      setLoading(false)
116
+      setList(res)
117
+
118
+    }).catch(err => {
119
+      setLoading(false)
120
+
121
+    })
122
+
123
+  }, [])
124
+
125
+  return (
126
+    <Card title='企业数据总览' loading={loading} bodyStyle={{ height: 600 }}>
127
+      <Echart option={option} />
128
+    </Card>
129
+  )
130
+}

+ 124
- 0
src/pages/orgDashboard/components/ReportList.jsx 查看文件

@@ -0,0 +1,124 @@
1
+import moment from 'moment'
2
+import { Card, List, Badge, Space, Carousel } from 'antd'
3
+import { useCallback, useEffect, useMemo, useState } from 'react'
4
+import { getList } from '@/services/work'
5
+import { random } from '@/utils/number'
6
+import { useModel } from 'umi'
7
+
8
+const colorList = [
9
+  '#a8071a',
10
+  '#ad2102',
11
+  '#ad4e00',
12
+  '#ad6800',
13
+  '#ad8b00',
14
+  '#5b8c00',
15
+  '#237804',
16
+  '#006d75',
17
+  '#0050b3',
18
+  '#10239e',
19
+  '#391085',
20
+  '#9e1068',
21
+]
22
+
23
+const Avatar = (props) => {
24
+  const style = useMemo(() => {
25
+    let r = random(0, colorList.length)
26
+    if (r >= 12) r = 0;
27
+    const color = colorList[r];
28
+
29
+    return {
30
+      background: color,
31
+      color: '#fff',
32
+      width: '48px',
33
+      height: '48px',
34
+      fontSize: '1.8em',
35
+      lineHeight: '48px',
36
+      textAlign: 'center',
37
+    }
38
+  }, [])
39
+
40
+  return <div style={style}>{props.children}</div>
41
+}
42
+
43
+
44
+const Content = (props) => {
45
+  const { item } = props;
46
+
47
+  const abnormal = item.antigenIsNormal === 0 || item.nucleicIsNormal === 0
48
+  const status = abnormal ? 'error' : 'success'
49
+
50
+  return (
51
+    <Space size="large">
52
+      <span><Badge status={status} /> {abnormal ? '异常' : '正常'}</span>
53
+      <span>{moment(item.createDate).format('HH:mm')}</span>
54
+    </Space>
55
+  )
56
+}
57
+
58
+const showNum = 8;
59
+
60
+export default (props) => {
61
+  const [loading, setLoading] = useState(false)
62
+  const [list, setList] = useState([])
63
+  const [disabled, setDisabled] = useState(false)
64
+  const { initialState } = useModel('@@initialState');
65
+
66
+
67
+  const queryList = useCallback(() => {
68
+    setLoading(true)
69
+    getList(
70
+      {
71
+        pageSize: 50, // 过多会很卡
72
+        start: moment().format('YYYY-MM-DD'),
73
+        end: moment().format('YYYY-MM-DD'),
74
+        isAll: true,
75
+        orgId: initialState.currentUser.orgId,
76
+      }).then(res => {
77
+        setLoading(false)
78
+        setList((res.records || []).reverse())
79
+      }).catch(er => {
80
+        setLoading(false)
81
+      })
82
+  }, [])
83
+
84
+  useEffect(() => {
85
+    queryList()
86
+  }, [])
87
+
88
+  useEffect(() => {
89
+    setDisabled(!list || list.length <= showNum)
90
+  }, [list])
91
+
92
+  return (
93
+    <Card title="今日提交记录" loading={loading} bodyStyle={{ height: '600px' }}>
94
+      <List style={{ height: '100%', overflow: 'hidden' }} itemLayout="horizontal">
95
+        <Carousel
96
+          autoplay={!disabled}
97
+          infinite={!disabled}
98
+          rtl
99
+          slidesToShow={showNum}
100
+          slidesToScroll={1}
101
+          dot={false}
102
+          dotPosition="right"
103
+          style={{ height: '100%' }}
104
+        >
105
+          {
106
+            list.map(item => (
107
+              <div key={item.formId} style={{ display: 'flex' }}>
108
+                <List.Item>
109
+                  <List.Item.Meta
110
+                    avatar={<Avatar>{item.orgName.substring(0, 1)}</Avatar>}
111
+                    title={item.userName}
112
+                    con
113
+                    description={item.orgName}
114
+                  />
115
+                  <Content item={item} />
116
+                </List.Item>
117
+              </div>
118
+            ))
119
+          }
120
+        </Carousel>
121
+      </List>
122
+    </Card>
123
+  )
124
+}

+ 41
- 0
src/pages/orgDashboard/components/StatisCard.jsx 查看文件

@@ -0,0 +1,41 @@
1
+import React from 'react'
2
+import { Statistic, Card } from 'antd';
3
+
4
+const iconDivStyle = {
5
+  position: 'absolute',
6
+  top: 20,
7
+  right: 20,
8
+}
9
+
10
+const iconStyle = {
11
+  fontSize: '5em',
12
+  color: '#fff',
13
+  opacity: 0.3,
14
+}
15
+
16
+export default (props) => {
17
+  const { title, value, icon, backColor = '#fff', frontColor='#000', onClick } = props
18
+
19
+  const bodyStyle = {
20
+    background: backColor,
21
+    overflow: 'hidden',
22
+    position: 'relative',
23
+  }
24
+
25
+  return (
26
+    <Card bodyStyle={bodyStyle} onClick={onClick}>
27
+      <Statistic
28
+        title={title}
29
+        value={value}
30
+        valueStyle={{ color: frontColor }}
31
+      />
32
+      {
33
+        icon && (
34
+          <div style={iconDivStyle}>
35
+            {React.cloneElement(icon, { style: iconStyle })}
36
+          </div>
37
+        )
38
+      }
39
+    </Card>
40
+  )
41
+}

+ 78
- 0
src/pages/orgDashboard/components/StatisGroup.jsx 查看文件

@@ -0,0 +1,78 @@
1
+import React, { useState } from 'react';
2
+import { StatisticCard } from '@ant-design/pro-card';
3
+
4
+const { Divider } = StatisticCard;
5
+const iconDivStyle = {
6
+  position: 'absolute',
7
+  top: '4px',
8
+  right: '-30px',
9
+}
10
+
11
+const iconStyle = {
12
+  fontSize: '10em',
13
+  color: '#fff',
14
+  opacity: 0.45,
15
+}
16
+
17
+export default (props) => {
18
+  const { title, data1, data2, icon, onClick1, onClick2, backColor = '#fff', frontColor = '#000' } = props
19
+
20
+  const headStyle = {
21
+    background: backColor,
22
+    color: frontColor,
23
+  }
24
+
25
+  const bodyStyle = {
26
+    background: backColor,
27
+    color: frontColor,
28
+    position: 'relative',
29
+    overflow: 'hidden',
30
+  }
31
+
32
+  const groupBodyStyle = {
33
+    ...bodyStyle,
34
+    padding: 0,
35
+  }
36
+
37
+  const valueStyle = {
38
+    color: frontColor
39
+  }
40
+
41
+  const headTitleStyle = {
42
+    color: frontColor,
43
+    fontSize: '19px',
44
+    fontWeight: 700,
45
+    letterSpacing: '2px',
46
+  }
47
+
48
+  const titleStyle = {
49
+    color: frontColor,
50
+  }
51
+
52
+  return (
53
+    <StatisticCard.Group title={<div style={headTitleStyle}>{title}</div>} headStyle={headStyle} bodyStyle={groupBodyStyle}>
54
+      <StatisticCard
55
+        bodyStyle={bodyStyle}
56
+        statistic={{ ...data1, title: (<div style={titleStyle}>{data1.title}</div>), valueStyle }}
57
+        onClick={onClick1}
58
+      />
59
+      <Divider type="vertical" />
60
+      <StatisticCard
61
+        bodyStyle={bodyStyle}
62
+        statistic={
63
+          data2.value == -1 ?
64
+            { ...data2, value: ' ', title: (<div style={titleStyle}>{data2.title}</div>), valueStyle }
65
+            :
66
+            { ...data2, title: (<div style={titleStyle}>{data2.title}</div>), valueStyle }}
67
+        onClick={onClick2}
68
+      />
69
+      {
70
+        icon && (
71
+          <div style={iconDivStyle}>
72
+            {React.cloneElement(icon, { style: iconStyle })}
73
+          </div>
74
+        )
75
+      }
76
+    </StatisticCard.Group>
77
+  )
78
+}

+ 20
- 0
src/pages/orgDashboard/index.jsx 查看文件

@@ -0,0 +1,20 @@
1
+import React from 'react';
2
+import { Space, Row, Col } from 'antd'
3
+import ReportList from './components/ReportList';
4
+import OrgSummary from './components/OrgSummary';
5
+import BannerStatis from './components/BannerStatis';
6
+
7
+export default (props) => {  
8
+  return (
9
+    <Space direction="vertical" size="large" style={{ width: '100%' }}>
10
+      <BannerStatis />
11
+
12
+      <Row gutter={24}>
13
+        <Col span={12}><OrgSummary /></Col>
14
+        <Col span={12}>
15
+          <ReportList />
16
+        </Col>
17
+      </Row>
18
+    </Space>
19
+  )
20
+}

+ 7
- 0
src/services/statis.js 查看文件

@@ -5,3 +5,10 @@ export const getcomm = (params) => request('/statis/comm', { params });
5 5
 
6 6
 // 获取企业信息汇总
7 7
 export const getAllOrgPersonNum = () => request('/statis/org/total');
8
+
9
+// org工作台--企业数据总览
10
+export const getAllOrgLine = (params) => request('/statis/org/daily', { params, method: 'GET' });
11
+
12
+
13
+// org工作台--企业工作台数据
14
+export const getOrgComm = (params) => request('/statis/org/comm', { params });