Ver Fonte

fix(compiler): 首页修改为数据面板展示

shylock há 1 mês atrás
pai
commit
a3bca0ef80

+ 1 - 1
.eslintignore

@@ -5,4 +5,4 @@
 public
 dist
 .umi
-mock
+mock

+ 1 - 1
package.json

@@ -60,7 +60,7 @@
     "echarts": "^5.4.0",
     "js-md5": "^0.7.3",
     "jsonpath-plus": "^7.2.0",
-    "lodash": "^4.17.0",
+    "lodash": "^4.17.21",
     "moment": "^2.29.0",
     "mqtt": "^4.3.7",
     "omit.js": "^2.0.2",

BIN
public/assets/app-icon.png


BIN
public/assets/month-icon.png


BIN
public/assets/today-icon.png


BIN
public/assets/user-icon.png


+ 104 - 0
src/components/EchartsCommon/barChart.tsx

@@ -0,0 +1,104 @@
+import React, { useEffect, useRef } from 'react';
+import * as echarts from 'echarts';
+
+interface propsData {
+  xData: string[];
+  yData: string[];
+  color: string;
+  width: string;
+  height: string;
+}
+
+const LineChart: React.FC<propsData> = (props) => {
+  const chartRef: any = useRef();
+  const { xData, yData, color, width, height } = props;
+
+  // 初始化
+  useEffect(() => {
+    console.log(xData, yData);
+    const chart = echarts.init(chartRef.current);
+    const options = {
+      legend: {
+        show: false,
+      },
+      grid: {
+        left: '2%',
+        right: '2%',
+        bottom: '2%',
+        top: '3%',
+        containLabel: true,
+      },
+      xAxis: {
+        type: 'value',
+        splitLine: {
+          lineStyle: {
+            color: '#b0b0b0',
+            type: 'dashed',
+          },
+        },
+        axisTick: {
+          show: false,
+        },
+
+        axisLabel: {
+          //  改变x轴字体颜色和大小
+          textStyle: {
+            color: '#858585',
+            fontSize: 14,
+          },
+        },
+      },
+      yAxis: {
+        type: 'category',
+        data: ['响水', '滨海', '滨海', '东海', '徐州', '响水'],
+        splitLine: {
+          show: false,
+        },
+        axisTick: {
+          show: false,
+        },
+        axisLine: {
+          //  改变y轴颜色
+          lineStyle: {
+            color: '#b0b0b0',
+          },
+        },
+        axisLabel: {
+          textStyle: {
+            color: '#858585',
+            fontSize: 14,
+          },
+        },
+      },
+      series: [
+        {
+          type: 'bar',
+          name: '产出',
+          barWidth: 15,
+          itemStyle: {
+            normal: {
+              label: {
+                show: true, //开启显示
+                position: 'insideRight', //在上方显示
+                textStyle: {
+                  //数值样式
+                  color: '#FFFFFF',
+                  fontSize: 12,
+                  fontWeight: 600,
+                },
+              },
+              color: color,
+              barBorderRadius: 15,
+            },
+          },
+          data: [19, 29, 39, 81, 29, 39],
+        },
+      ],
+    };
+
+    chart.setOption(options);
+  }, []);
+
+  return <div style={{ width: width, height: height }} ref={chartRef} />;
+};
+export default LineChart;

+ 137 - 0
src/components/EchartsCommon/lineChart.tsx

@@ -0,0 +1,137 @@
+import React, { useEffect, useRef } from 'react';
+import * as echarts from 'echarts';
+
+interface propsData {
+  xData: string[];
+  yData: string[];
+  color: string;
+  width: string;
+  height: string;
+}
+
+const LineChart: React.FC<propsData> = (props) => {
+  const chartRef: any = useRef();
+  const { xData, yData, color, width, height } = props;
+
+  // 初始化
+  useEffect(() => {
+    console.log(xData, yData);
+    const chart = echarts.init(chartRef.current);
+    const options = {
+      legend: {
+        show: false,
+      },
+      tooltip: {
+        trigger: 'axis',
+      },
+      grid: {
+        left: '3%',
+        right: '3%',
+        bottom: '3%',
+        top: '5%',
+        containLabel: true,
+      },
+      xAxis: [
+        {
+          type: 'category',
+          data: ['A', 'B', 'C', 'D', 'E', 'F', 'G'],
+          axisLine: {
+            lineStyle: {
+              color: '#ddd',
+            },
+          },
+          axisTick: {
+            show: false,
+          },
+          axisLabel: {
+            interval: 0,
+            textStyle: {
+              color: '#333',
+            },
+            margin: 15,
+          },
+          boundaryGap: false,
+        },
+      ],
+      yAxis: [
+        {
+          type: 'value',
+          axisTick: {
+            show: false,
+          },
+          axisLine: {
+            lineStyle: {
+              color: '#ddd',
+            },
+          },
+          axisLabel: {
+            textStyle: {
+              color: '#333',
+            },
+          },
+          splitLine: {
+            show: false,
+          },
+        },
+      ],
+      series: [
+        {
+          name: 'S',
+          type: 'line',
+          data: [13, 10, 3, 12, 15, 30, 7],
+          symbolSize: 6,
+          symbol: 'circle',
+          smooth: true,
+          lineStyle: {
+            color: color,
+          },
+          itemStyle: {
+            normal: {
+              color: color,
+              borderColor: color,
+            },
+          },
+          areaStyle: {
+            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+              {
+                offset: 0,
+                color: color + 'b3',
+              },
+              {
+                offset: 1,
+                color: color + '03',
+              },
+            ]),
+          },
+          emphasis: {
+            itemStyle: {
+              color: {
+                type: 'radial',
+                x: 0.5,
+                y: 0.5,
+                r: 0.5,
+                colorStops: [
+                  {
+                    offset: 0,
+                    color: color,
+                  },
+                  {
+                    offset: 1,
+                    color: '#fff',
+                  },
+                ],
+              },
+              borderColor: color,
+              borderWidth: 2,
+            },
+          },
+        },
+      ],
+    };
+
+    chart.setOption(options);
+  }, []);
+
+  return <div style={{ width: width, height: height }} ref={chartRef} />;
+};
+export default LineChart;

+ 3 - 2
src/pages/MenuManagement/edit.tsx

@@ -14,6 +14,7 @@ import {
 import React, { useEffect, useState } from 'react';
 import IconSelector from '@/components/IconSelecter';
 import { createMenu, editMenu, queryMenu } from '@/services/menu';
+import _ from 'lodash';
 
 interface editProps {
   visible: boolean;
@@ -45,7 +46,7 @@ const Edit: React.FC<editProps> = (props) => {
   }, []);
 
   // 确认弹框
-  const onOk = () => {
+  const onOk = _.throttle(() => {
     form.validateFields().then((values) => {
       if (values) {
         const data = { ...values };
@@ -83,7 +84,7 @@ const Edit: React.FC<editProps> = (props) => {
         }
       }
     });
-  };
+  }, 2000);
 
   // 取消
   const onCancel = () => {

+ 50 - 112
src/pages/Welcome.less

@@ -1,123 +1,61 @@
 @import (reference) '~antd/es/style/themes/index';
 
-.container {
-  .itemLeft {
-    box-sizing: border-box;
-    height: 100%;
-    padding: 40px 0 30px 30px;
-    overflow: hidden;
-    color: #fff;
-    background: url('../../public/assets/book-bg.jpg');
-    background-size: cover;
-    border-radius: 20px;
-    .leftTitle {
-      font-size: 20px;
-    }
-    .imgBox {
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      width: 90px;
-      height: 90px;
-      margin: 40px 0 20px;
-      background-color: #fff;
-      border-radius: 20px;
-      box-shadow: 0 10px 20px rgb(0 0 0 / 14%);
-    }
-    .leftNumber {
-      overflow: hidden;
-      font-size: 62px;
-    }
-  }
-  .itemCenter {
-    height: 100%;
-    padding: 40px;
-    background: #f2f8f3;
-    border-radius: 25px;
-    .itemImg {
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      width: 70px;
-      height: 70px;
-      margin: 0 auto;
-      background: #fff;
-      border-radius: 20px;
-
-      img {
-        width: 50px;
-        height: 50px;
-      }
-    }
-    .itemValue {
-      margin-top: 40px;
-      font-weight: bold;
-      font-size: 28px;
+.welcomeTitle {
+  margin-bottom: 15px;
+  font-weight: bold;
+  font-size: 18px;
+}
+.timeSearch {
+  display: flex;
+  justify-content: space-between;
+}
+.dataOverviewTitle {
+  color: #1890ff;
+  font-weight: bold;
+  font-size: 18px;
+  font-style: italic;
+}
+.dataTop {
+  .dataItem {
+    margin-top: 20px;
+    background: #f2f6fa;
+    .dataTitle {
+      color: gray;
       text-align: center;
     }
-    .itemTitle {
-      overflow: hidden;
-      color: #1a1a37;
-      font-size: 15px;
-      white-space: nowrap;
+    .dataValue {
+      align-items: center;
+      margin-top: 13px;
       text-align: center;
-    }
-  }
-  .itemRight {
-    display: flex;
-    flex-wrap: wrap;
-    width: 100%;
-    height: 100%;
-    .imgRightBox {
-      display: flex;
-      flex-direction: column;
-      box-sizing: border-box;
-      width: 45%;
-      margin: 10px;
-      padding: 25px;
-      border-radius: 30px;
-      .itemRightImg {
-        display: flex;
-        align-items: center;
-        justify-content: center;
-        width: 70px;
-        height: 70px;
-        margin-bottom: 10px;
-        background-color: #fff;
-        border-radius: 19px;
-        img {
-          width: 33px;
-          height: 33px;
-        }
-      }
-      .itemRightVal {
-        margin-bottom: 4px;
-        color: #1a1a37;
+      .dataNum {
+        margin-right: 6px;
+        color: #333;
         font-weight: bold;
-        font-size: 28px;
+        font-size: 30px;
       }
-      .itemRightTitle {
-        overflow: hidden;
-        color: #1a1a37;
-        font-size: 15px;
-        white-space: nowrap;
-      }
-    }
-    .itemRightBg1 {
-      background: #e8faea url('../../public/icons/1-bg.png');
-      background-size: 100% 100%;
-    }
-    .itemRightBg2 {
-      background: #e7e1fb url('../../public/icons/2-bg.png');
-      background-size: 100% 100%;
     }
-    .itemRightBg3 {
-      background: #fdf3e9 url('../../public/icons/3-bg.png');
-      background-size: 100% 100%;
-    }
-    .itemRightBg4 {
-      background: #f0f5fb url('../../public/icons/4-bg.png');
-      background-size: 100% 100%;
+  }
+}
+
+.userDataItem {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  .dataItemTitle {
+    margin-bottom: 25px;
+    font-weight: bold;
+  }
+  .dataItemValue {
+    margin-top: 20px;
+    font-weight: bold;
+    font-size: 30px;
+  }
+  .dataItemIcon {
+    padding: 10px;
+    background: #f2f6fa;
+    border-radius: 10px;
+    img {
+      width: 50px;
     }
   }
 }

+ 203 - 85
src/pages/Welcome.tsx

@@ -3,15 +3,15 @@ import { Button, Card, Col, DatePicker, Form, Row, Space } from 'antd';
 import React, { useEffect, useRef, useState } from 'react';
 import styles from './Welcome.less';
 import { getStatisticData } from '@/services/statistic';
-import bookSum from '../../public/assets/book-sum.png';
-import totalOnlineNum from '../../public/icons/total_online_num.png';
-import activation1 from '../../public/icons/activation_1.png';
-import activation2 from '../../public/icons/activation_2.png';
-import online1 from '../../public/icons/online_1.png';
-import online2 from '../../public/icons/online_2.png';
 import { ReloadOutlined, SearchOutlined } from '@ant-design/icons';
 import moment from 'moment/moment';
 import * as echarts from 'echarts';
+import userIcon from '../../public/assets/user-icon.png';
+import appIcon from '../../public/assets/app-icon.png';
+import monthIcon from '../../public/assets/month-icon.png';
+import todayIcon from '../../public/assets/today-icon.png';
+import LineChart from '@/components/EchartsCommon/lineChart';
+import BarChart from '@/components/EchartsCommon/barChart';
 
 const { RangePicker } = DatePicker;
 
@@ -36,27 +36,59 @@ const Welcome: React.FC = () => {
         const chart = echarts.init(chartRef.current);
         const region = JSON.parse(res.data.region);
         const newData = Object.entries(region).map(([name, value]) => ({ value, name }));
-        console.log(newData);
         const options = {
           tooltip: {
             trigger: 'item',
           },
           legend: {
+            type: 'plain',
+            icon: 'circle',
             orient: 'vertical',
-            left: 'left',
+            left: 40,
           },
           series: [
             {
               type: 'pie',
-              radius: '50%',
+              radius: [175, 200],
+              center: ['65%', '50%'],
               data: newData,
-              emphasis: {
-                itemStyle: {
-                  shadowBlur: 10,
-                  shadowOffsetX: 0,
-                  shadowColor: 'rgba(0, 0, 0, 0.5)',
+              avoidLabelOverlap: false,
+              padAngle: 5,
+              itemStyle: {
+                borderRadius: 10,
+              },
+              label: {
+                normal: {
+                  show: false,
+                  position: 'center',
+                  formatter: '{text|{c}}\n{b}',
+                  rich: {
+                    text: {
+                      align: 'center',
+                      verticalAlign: 'middle',
+                      padding: 8,
+                      fontSize: 50,
+                      fontWeight: 'bold',
+                      color: '#333',
+                    },
+                    value: {
+                      align: 'center',
+                      verticalAlign: 'middle',
+                      fontSize: 20,
+                      color: '#bfbfbf',
+                    },
+                  },
+                },
+                emphasis: {
+                  show: true,
+                  textStyle: {
+                    fontSize: '12',
+                  },
                 },
               },
+              labelLine: {
+                show: false,
+              },
             },
           ],
         };
@@ -92,84 +124,170 @@ const Welcome: React.FC = () => {
     setSearchData(null);
   };
 
+  // 千分号格式化
+  // const formatNumber = (num: any) => {
+  //   if (num === null || num === undefined || isNaN(num)) return '';
+  //   return parseFloat(num).toLocaleString(undefined, {
+  //     maximumFractionDigits: 20,
+  //   });
+  // };
+
   return (
     <PageContainer>
-      <Card style={{ marginBottom: '20px' }}>
-        <Form form={form} layout="inline" onFinish={onFinish}>
-          <Form.Item name="time" label="时间">
-            <RangePicker />
-          </Form.Item>
-          <Form.Item style={{ marginBottom: '10px' }}>
-            <Space>
-              <Button type="primary" htmlType="submit">
-                <SearchOutlined />
-                查询
-              </Button>
-              <Button htmlType="button" onClick={onReset}>
-                <ReloadOutlined />
-                重置
-              </Button>
-            </Space>
-          </Form.Item>
-        </Form>
-      </Card>
-      <Card className={styles.container}>
-        <Row gutter={[30, 20]}>
-          <Col span={5} xs={24} sm={12} md={12} lg={12} xl={5} xxl={5}>
-            <div className={styles.itemLeft}>
-              <span className={styles.leftTitle}>总数</span>
-              <div className={styles.imgBox}>
-                <img src={bookSum} alt="" />
-              </div>
-              <span className={styles.leftNumber}>{data?.total}</span>
-            </div>
-          </Col>
-          <Col span={3} xs={24} sm={12} md={12} lg={12} xl={3} xxl={3}>
-            <div className={styles.itemCenter}>
-              <div className={styles.itemImg}>
-                <img src={totalOnlineNum} alt="" />
-              </div>
-              <div className={styles.itemValue}>{data?.online}</div>
-              <div className={styles.itemTitle}>总在线数</div>
-            </div>
-          </Col>
-          <Col span={8} xs={24} sm={12} md={12} lg={12} xl={8} xxl={8}>
-            <div className={styles.itemRight}>
-              <div className={[styles.imgRightBox, styles.itemRightBg4].join(' ')}>
-                <div className={styles.itemRightImg}>
-                  <img src={online2} alt="" />
+      <Card style={{ marginBottom: '20px' }} hoverable>
+        <div className={styles.welcomeTitle}>Hi,欢迎使用永续绿建运营管理平台!</div>
+        <div className={styles.timeSearch}>
+          <div className={styles.dataOverviewTitle}>数据总览</div>
+          <Form form={form} layout="inline" onFinish={onFinish}>
+            <Form.Item name="time" label="时间">
+              <RangePicker />
+            </Form.Item>
+            <Form.Item style={{ marginBottom: '10px' }}>
+              <Space>
+                <Button type="primary" htmlType="submit">
+                  <SearchOutlined />
+                  查询
+                </Button>
+                <Button htmlType="button" onClick={onReset}>
+                  <ReloadOutlined />
+                  重置
+                </Button>
+              </Space>
+            </Form.Item>
+          </Form>
+        </div>
+
+        <div className={styles.dataTop}>
+          <Row gutter={[20, 20]}>
+            <Col flex="1">
+              <Card className={styles.dataItem} bordered={false}>
+                <div className={styles.dataTitle}>设备总数</div>
+                <div className={styles.dataValue}>
+                  <span className={styles.dataNum}>{data?.total}</span>
+                  <span style={{ color: 'gray' }}>台</span>
                 </div>
-                <span className={styles.itemRightVal}>{data?.wuheng_online}</span>
-                <span className={styles.itemRightTitle}>五恒在线数</span>
-              </div>
-              <div className={[styles.imgRightBox, styles.itemRightBg1].join(' ')}>
-                <div className={styles.itemRightImg}>
-                  <img src={activation2} alt="" />
+              </Card>
+            </Col>
+            <Col flex="1">
+              <Card className={styles.dataItem} bordered={false}>
+                <div className={styles.dataTitle}>总在线数</div>
+                <div className={styles.dataValue}>
+                  <span className={styles.dataNum}>{data?.online}</span>
+                  <span style={{ color: 'gray' }}>台</span>
                 </div>
-                <span className={styles.itemRightVal}>{data?.wuheng}</span>
-                <span className={styles.itemRightTitle}>激活五恒数</span>
-              </div>
-              <div className={[styles.imgRightBox, styles.itemRightBg3].join(' ')}>
-                <div className={styles.itemRightImg}>
-                  <img src={online1} alt="" />
+              </Card>
+            </Col>
+            <Col flex="1">
+              <Card className={styles.dataItem} bordered={false}>
+                <div className={styles.dataTitle}>五恒在线数</div>
+                <div className={styles.dataValue}>
+                  <span className={styles.dataNum}>{data?.wuheng_online}</span>
+                  <span style={{ color: 'gray' }}>台</span>
                 </div>
-                <span className={styles.itemRightVal}>{data?.ffx_online}</span>
-                <span className={styles.itemRightTitle}>分风箱在线数</span>
-              </div>
-              <div className={[styles.imgRightBox, styles.itemRightBg2].join(' ')}>
-                <div className={styles.itemRightImg}>
-                  <img src={activation1} alt="" />
+              </Card>
+            </Col>
+            <Col flex="1">
+              <Card className={styles.dataItem} bordered={false}>
+                <div className={styles.dataTitle}>激活五恒数</div>
+                <div className={styles.dataValue}>
+                  <span className={styles.dataNum}>{data?.wuheng}</span>
+                  <span style={{ color: 'gray' }}>台</span>
                 </div>
-                <span className={styles.itemRightVal}>{data?.ffx}</span>
-                <span className={styles.itemRightTitle}>激活分风箱数</span>
-              </div>
-            </div>
-          </Col>
-          <Col span={8} xs={24} sm={12} md={12} lg={12} xl={8} xxl={8}>
-            <div style={{ width: '700px', height: '450px' }} ref={chartRef} />
-          </Col>
-        </Row>
+              </Card>
+            </Col>
+            <Col flex="1">
+              <Card className={styles.dataItem} bordered={false}>
+                <div className={styles.dataTitle}>分风箱在线数</div>
+                <div className={styles.dataValue}>
+                  <span className={styles.dataNum}>{data?.ffx_online}</span>
+                  <span style={{ color: 'gray' }}>台</span>
+                </div>
+              </Card>
+            </Col>
+          </Row>
+        </div>
       </Card>
+
+      <Row gutter={[20, 20]}>
+        <Col span={16}>
+          <div>
+            <Row gutter={[20, 20]}>
+              <Col span={6}>
+                <Card hoverable>
+                  <div className={styles.userDataItem}>
+                    <div>
+                      <div className={styles.dataItemTitle}>用户数</div>
+                      <div className={styles.dataItemValue}>222</div>
+                    </div>
+                    <div className={styles.dataItemIcon}>
+                      <img src={userIcon} alt="用户icon" />
+                    </div>
+                  </div>
+                </Card>
+              </Col>
+              <Col span={6}>
+                <Card hoverable>
+                  <div className={styles.userDataItem}>
+                    <div>
+                      <div className={styles.dataItemTitle}>今日新增</div>
+                      <div className={styles.dataItemValue}>222</div>
+                    </div>
+                    <div className={styles.dataItemIcon}>
+                      <img src={todayIcon} alt="今日新增icon" />
+                    </div>
+                  </div>
+                </Card>
+              </Col>
+              <Col span={6}>
+                <Card hoverable>
+                  <div className={styles.userDataItem}>
+                    <div>
+                      <div className={styles.dataItemTitle}>本月新增</div>
+                      <div className={styles.dataItemValue}>222</div>
+                    </div>
+                    <div className={styles.dataItemIcon}>
+                      <img src={monthIcon} alt="本月新增icon" />
+                    </div>
+                  </div>
+                </Card>
+              </Col>
+              <Col span={6}>
+                <Card hoverable>
+                  <div className={styles.userDataItem}>
+                    <div>
+                      <div className={styles.dataItemTitle}>App统计次数</div>
+                      <div className={styles.dataItemValue}>222</div>
+                    </div>
+                    <div className={styles.dataItemIcon}>
+                      <img src={appIcon} alt="App统计次数icon" />
+                    </div>
+                  </div>
+                </Card>
+              </Col>
+            </Row>
+            <Row gutter={[20, 20]} style={{ marginTop: '20px' }}>
+              <Col span={12}>
+                <Card hoverable>
+                  <div style={{ marginBottom: '20px', fontWeight: 'bold' }}>日活用户统计</div>
+                  <LineChart color="#1890ff" height="450px" width="700px" xData={[]} yData={[]} />
+                </Card>
+              </Col>
+              <Col span={12}>
+                <Card hoverable>
+                  <div style={{ marginBottom: '20px', fontWeight: 'bold' }}>设备类型统计</div>
+                  <BarChart color="#1890ff" height="450px" width="700px" xData={[]} yData={[]} />
+                </Card>
+              </Col>
+            </Row>
+          </div>
+        </Col>
+        <Col span={8}>
+          <Card hoverable>
+            <div style={{ marginBottom: '20px', fontWeight: 'bold' }}>设备使用地区统计</div>
+            <div style={{ width: '700px', height: '620px' }} ref={chartRef} />
+          </Card>
+        </Col>
+      </Row>
     </PageContainer>
   );
 };