Просмотр исходного кода

feat(DashBoardTopCard): 添加DashBoardTopCard组件

xieyonghong 3 лет назад
Родитель
Сommit
1144c6aff2

BIN
public/images/media/dashboard-1.png


BIN
public/images/media/dashboard-2.png


BIN
public/images/media/dashboard-3.png


BIN
public/images/media/dashboard-4.png


+ 76 - 0
src/components/DashBoard/index.less

@@ -37,3 +37,79 @@
   flex: 1;
   height: 100%;
 }
+
+.dash-board-top {
+  margin-bottom: 24px;
+
+  .dash-board-top-item {
+    display: flex;
+    flex-direction: column;
+    height: 100%;
+    padding: 24px;
+    background-color: #fff;
+    border: 1px solid #e0e4e8;
+    border-radius: 2px;
+
+    .top-item-content {
+      display: flex;
+      flex-direction: column;
+      flex-grow: 1;
+
+      .content-left {
+        width: 50%;
+
+        .content-left-title {
+          color: rgba(0, 0, 0, 0.64);
+        }
+
+        .content-left-value {
+          padding: 12px 0;
+          color: #323130;
+          font-weight: bold;
+          font-size: 36px;
+        }
+      }
+
+      .content-right {
+        display: flex;
+        flex-grow: 1;
+        align-items: flex-end;
+        justify-content: flex-end;
+        width: 100%;
+        height: 0;
+
+        > * {
+          max-width: 100%;
+          max-height: 100%;
+        }
+      }
+
+      &.show-value {
+        flex-direction: row;
+
+        .content-left {
+          height: 100%;
+        }
+
+        .content-right {
+          width: 0;
+          height: 100%;
+        }
+      }
+    }
+  }
+
+  .top-item-footer {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding-top: 16px;
+    border-top: 1px solid #f0f0f0;
+
+    .footer-item-value {
+      color: #323130;
+      font-weight: bold;
+      font-size: 16px;
+    }
+  }
+}

+ 1 - 0
src/components/DashBoard/index.tsx

@@ -2,5 +2,6 @@ import BaseCard from './baseCard';
 
 export { default as DashBoardEcharts } from './echarts';
 export { default as DashBoardHeader } from './header';
+export { default as DashBoardTopCard } from './topCard';
 
 export default BaseCard;

+ 72 - 2
src/components/DashBoard/topCard.tsx

@@ -1,3 +1,73 @@
-export default () => {
-  return <div></div>;
+import React from 'react';
+import { Badge, Col, Row } from 'antd';
+import classNames from 'classnames';
+import './index.less';
+
+interface TopCardProps {
+  children: React.ReactNode;
+  className?: string;
+  style?: React.CSSProperties;
+}
+
+interface FooterItem {
+  status?: 'error' | 'success' | 'warning';
+  title: string;
+  value: string | number;
+}
+
+interface CardItemProps {
+  span: number;
+  title: string;
+  value: any;
+  footer: false | FooterItem[];
+  showValue?: boolean;
+  children: React.ReactNode;
+}
+
+const CardItem = (props: CardItemProps) => {
+  return (
+    <Col span={props.span}>
+      <div className={'dash-board-top-item'}>
+        <div
+          className={classNames('top-item-content', { 'show-value': props.showValue !== false })}
+        >
+          <div className={'content-left'}>
+            <div className={'content-left-title'}>{props.title}</div>
+            {props.showValue !== false && <div className={'content-left-value'}>{props.value}</div>}
+          </div>
+          <div className={'content-right'}>{props.children}</div>
+        </div>
+        {props.footer !== false && props.footer.length ? (
+          <div className={'top-item-footer'}>
+            {props.footer.map((item) => {
+              return (
+                <>
+                  <div>
+                    {item.status ? (
+                      <Badge status={item.status} text={item.title} />
+                    ) : (
+                      <span>{item.title}</span>
+                    )}
+                  </div>
+                  <div className={'footer-item-value'}>{item.value}</div>
+                </>
+              );
+            })}
+          </div>
+        ) : null}
+      </div>
+    </Col>
+  );
 };
+
+const TopCard = (props: TopCardProps) => {
+  return (
+    <div className={classNames('dash-board-top', props.className)} style={props.style}>
+      <Row gutter={24}>{props.children}</Row>
+    </div>
+  );
+};
+
+TopCard.Item = CardItem;
+
+export default TopCard;

+ 70 - 66
src/pages/media/DashBoard/index.tsx

@@ -1,38 +1,15 @@
 import { PageContainer } from '@ant-design/pro-layout';
-import { Badge, Card } from 'antd';
-import DashBoard from '@/components/DashBoard';
+import DashBoard, { DashBoardTopCard } from '@/components/DashBoard';
 import { useRequest } from 'umi';
-import React, { useEffect, useState } from 'react';
+import { useEffect, useState } from 'react';
 import Service from './service';
 import './index.less';
 import encodeQuery from '@/utils/encodeQuery';
 import type { EChartsOption } from 'echarts';
 import moment from 'moment';
 
-interface TopCardProps {
-  url: string;
-  title: string;
-  total: number | string;
-  bottomRender: () => React.ReactNode;
-}
-
 const service = new Service('media');
 
-const TopCard = (props: TopCardProps) => {
-  return (
-    <div className={'top-card-item'}>
-      <div className={'top-card-top'}>
-        <div className={'top-card-top-left'}></div>
-        <div className={'top-card-top-right'}>
-          <div className={'top-card-title'}>{props.title}</div>
-          <div className={'top-card-total'}>{props.total}</div>
-        </div>
-      </div>
-      <div className={'top-card-bottom'}>{props.bottomRender()}</div>
-    </div>
-  );
-};
-
 export default () => {
   const [deviceOnline, setDeviceOnline] = useState(0);
   const [deviceOffline, setDeviceOffline] = useState(0);
@@ -122,6 +99,12 @@ export default () => {
         yAxis: {
           type: 'value',
         },
+        grid: {
+          left: '2%',
+          right: '2%',
+          top: '2%',
+          bottom: '2%',
+        },
         series: [
           {
             data: sData,
@@ -164,51 +147,72 @@ export default () => {
   return (
     <PageContainer>
       <div className={'media-dash-board'}>
-        <Card className={'top-card-items'} bodyStyle={{ display: 'flex', gap: 12 }}>
-          <TopCard
+        <DashBoardTopCard>
+          <DashBoardTopCard.Item
             title={'设备数量'}
-            total={deviceTotal}
-            url={''}
-            bottomRender={() => (
-              <>
-                <Badge status="success" text="在线" />{' '}
-                <span style={{ padding: '0 4px' }}>{deviceOnline}</span>
-                <Badge status="error" text="离线" />{' '}
-                <span style={{ padding: '0 4px' }}>{deviceOffline}</span>
-              </>
-            )}
-          />
-          <TopCard
+            value={deviceTotal}
+            footer={[
+              {
+                title: '在线',
+                value: deviceOnline,
+                status: 'success',
+              },
+              {
+                title: '离线',
+                value: deviceOffline,
+                status: 'error',
+              },
+            ]}
+            span={6}
+          >
+            <img src={require('/public/images/media/dashboard-1.png')} />
+          </DashBoardTopCard.Item>
+          <DashBoardTopCard.Item
             title={'通道数量'}
-            total={channelTotal}
-            url={''}
-            bottomRender={() => (
-              <>
-                <Badge status="success" text="已连接" />{' '}
-                <span style={{ padding: '0 4px' }}>{channelOnline}</span>
-                <Badge status="error" text="未连接" />{' '}
-                <span style={{ padding: '0 4px' }}>{channelOffline}</span>
-              </>
-            )}
-          />
-          <TopCard
+            value={channelTotal}
+            footer={[
+              {
+                title: '已连接',
+                value: channelOnline,
+                status: 'success',
+              },
+              {
+                title: '未连接',
+                value: channelOffline,
+                status: 'error',
+              },
+            ]}
+            span={6}
+          >
+            <img src={require('/public/images/media/dashboard-2.png')} />
+          </DashBoardTopCard.Item>
+          <DashBoardTopCard.Item
             title={'录像数量'}
-            total={fileObject ? fileObject.total : 0}
-            url={''}
-            bottomRender={() => (
-              <div>
-                总时长:
-                {handleTimeFormat(fileObject ? fileObject.duration : 0)}
-              </div>
-            )}
-          />
-          <TopCard
+            value={fileObject ? fileObject.total : 0}
+            footer={[
+              {
+                title: '总时长',
+                value: handleTimeFormat(fileObject ? fileObject.duration : 0),
+              },
+            ]}
+            span={6}
+          >
+            <img src={require('/public/images/media/dashboard-3.png')} />
+          </DashBoardTopCard.Item>
+          <DashBoardTopCard.Item
             title={'播放中数量'}
-            total={playObject ? playObject.playerTotal : 0}
-            url={''}
-            bottomRender={() => <div>播放人数: {playObject ? playObject.playingTotal : 0}</div>}
-          />
-        </Card>
+            value={playObject ? playObject.playerTotal : 0}
+            footer={[
+              {
+                title: '播放人数',
+                value: playObject ? playObject.playingTotal : 0,
+              },
+            ]}
+            span={6}
+          >
+            <img src={require('/public/images/media/dashboard-4.png')} />
+          </DashBoardTopCard.Item>
+        </DashBoardTopCard>
         <DashBoard
           className={'media-dash-board-body'}
           title={'播放数量(人次)'}