Преглед изворни кода

feat: 添加useDomFullHeight

xieyonghong пре 3 година
родитељ
комит
701bd019ea

+ 6 - 12
src/components/ProTableCard/index.tsx

@@ -1,14 +1,14 @@
 import type { ProTableProps } from '@jetlinks/pro-table';
 import ProTable from '@jetlinks/pro-table';
 import type { ParamsType } from '@ant-design/pro-provider';
-import React, { useCallback, useEffect, useState } from 'react';
+import React, { useCallback, useEffect, useRef, useState } from 'react';
 import { isFunction } from 'lodash';
 import { Empty, Pagination, Space } from 'antd';
 import { AppstoreOutlined, BarsOutlined } from '@ant-design/icons';
 import classNames from 'classnames';
 import LoadingComponent from '@ant-design/pro-layout/es/PageLoading';
 import './index.less';
-import { getDomFullHeight } from '@/utils/util';
+import { useDomFullHeight } from '@/hooks';
 
 enum ModelEnum {
   TABLE = 'TABLE',
@@ -40,7 +40,9 @@ const ProTableCard = <
   const [column, setColumn] = useState(props.gridColumn || 4);
   const [loading, setLoading] = useState(false);
   const [dataLength, setDataLength] = useState<number>(0);
-  const [minHeight, setMinHeight] = useState(100);
+
+  const domRef = useRef<HTMLDivElement>(null);
+  const { minHeight } = useDomFullHeight(domRef);
 
   /**
    * 处理 Card
@@ -144,15 +146,7 @@ const ProTableCard = <
   }, [props.params]);
 
   return (
-    <div
-      className={'pro-table-card'}
-      style={{ minHeight: minHeight }}
-      ref={(ref) => {
-        if (ref) {
-          setMinHeight(getDomFullHeight('pro-table-card'));
-        }
-      }}
-    >
+    <div className={'pro-table-card'} style={{ minHeight: minHeight }} ref={domRef}>
       <ProTable<T, U, ValueType>
         {...extraProps}
         params={

+ 65 - 0
src/hooks/document/useDomFullHeight.tsx

@@ -0,0 +1,65 @@
+import { useEffect, useState } from 'react';
+import type { MutableRefObject } from 'react';
+
+type TargetValue<T> = T | undefined | null;
+
+type TargetType = HTMLElement | HTMLDivElement | Element | Window | Document;
+
+type BasicTarget<T extends TargetType = Element> =
+  | TargetValue<T>
+  | MutableRefObject<TargetValue<T>>;
+
+const getTargetElement = <T extends TargetType>(target: BasicTarget<T> | string) => {
+  if (!target) {
+    return null;
+  }
+
+  let targetElement: TargetValue<T> | Element;
+
+  if (typeof target === 'string') {
+    targetElement = document.querySelector(target);
+  } else if ('current' in target) {
+    targetElement = target.current;
+  } else {
+    targetElement = target;
+  }
+
+  return targetElement;
+};
+
+const useDomFullHeight = (target: BasicTarget | string, extraHeight: number = 0) => {
+  const [state, setState] = useState(100);
+
+  useEffect(() => {
+    const el = getTargetElement(target);
+    let resizeObserver: ResizeObserver | undefined;
+    if (el) {
+      resizeObserver = new ResizeObserver((entries) => {
+        entries.forEach((entry) => {
+          const bodyClient = document.body.getBoundingClientRect();
+          const domClient = entry.target.getBoundingClientRect();
+          console.log(domClient);
+          if (domClient.y < 50) {
+            setState(100);
+          } else {
+            setState(bodyClient.height - domClient.y - 24 - extraHeight);
+          }
+        });
+      });
+
+      resizeObserver.observe(el);
+    }
+
+    return () => {
+      if (resizeObserver) {
+        resizeObserver.disconnect();
+      }
+    };
+  }, [target]);
+
+  return {
+    minHeight: state,
+  };
+};
+
+export default useDomFullHeight;

+ 1 - 0
src/hooks/index.ts

@@ -1,2 +1,3 @@
 export { default as useHistory } from './route/useHistory';
 export { default as useLocation } from './route/useLocation';
+export { default as useDomFullHeight } from './document/useDomFullHeight';

+ 4 - 3
src/pages/device/Category/index.tsx

@@ -12,7 +12,7 @@ import { observer } from '@formily/react';
 import type { Response } from '@/utils/typings';
 import SearchComponent from '@/components/SearchComponent';
 import { PermissionButton } from '@/components';
-import { getDomFullHeight } from '@/utils/util';
+import { useDomFullHeight } from '@/hooks';
 
 export const service = new Service('device/category');
 
@@ -54,6 +54,7 @@ const Category = observer(() => {
   const [treeData, setTreeData] = useState<any[]>([]);
   const permissionCode = 'device/Category';
   const { permission } = PermissionButton.usePermission(permissionCode);
+  const { minHeight } = useDomFullHeight(`.device-category`, 24);
 
   const intl = useIntl();
 
@@ -196,8 +197,8 @@ const Category = observer(() => {
             status: response.status,
           };
         }}
-        className={'device-category'}
-        tableStyle={{ minHeight: getDomFullHeight('device-category', 94) }}
+        tableClassName={'device-category'}
+        tableStyle={{ minHeight }}
         rowKey="id"
         columns={columns}
         onChange={(_, f, sorter: any) => {

+ 4 - 5
src/pages/device/Instance/Detail/ChildDevice/index.tsx

@@ -11,7 +11,7 @@ import BindChildDevice from './BindChildDevice';
 import moment from 'moment';
 import { Link } from 'umi';
 import { getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
-import { getDomFullHeight } from '@/utils/util';
+import { useDomFullHeight } from '@/hooks';
 
 const ChildDevice = () => {
   const intl = useIntl();
@@ -21,6 +21,8 @@ const ChildDevice = () => {
   const [searchParams, setSearchParams] = useState<any>({});
   const [bindKeys, setBindKeys] = useState<any[]>([]);
 
+  const { minHeight } = useDomFullHeight(`.device-detail-childDevice`);
+
   const unBindSingleDevice = async (id: string) => {
     const resp = await service.unbindDevice(InstanceModel.detail.id!, id, {});
     if (resp.status === 200) {
@@ -117,10 +119,7 @@ const ChildDevice = () => {
   ];
 
   return (
-    <Card
-      className={'device-detail-childDevice'}
-      style={{ minHeight: getDomFullHeight('device-detail-childDevice', 12) }}
-    >
+    <Card className={'device-detail-childDevice'} style={{ minHeight }}>
       <SearchComponent<LogItem>
         field={[...columns]}
         target="child-device"

+ 4 - 2
src/pages/device/Instance/Detail/Diagnose/index.tsx

@@ -7,7 +7,7 @@ import './index.less';
 import classNames from 'classnames';
 import { Store } from 'jetlinks-store';
 import { DiagnoseStatusModel } from './Status/model';
-import { getDomFullHeight } from '@/utils/util';
+import { useDomFullHeight } from '@/hooks';
 
 interface ListProps {
   key: string;
@@ -48,6 +48,8 @@ const Diagnose = () => {
   const [up, setUp] = useState<'success' | 'error' | 'waiting'>('waiting');
   const [down, setDown] = useState<'success' | 'error' | 'waiting'>('waiting');
 
+  const { minHeight } = useDomFullHeight(`.diagnose`, 12);
+
   const list = [
     {
       key: 'status',
@@ -132,7 +134,7 @@ const Diagnose = () => {
     };
   }, []);
   return (
-    <Card className="diagnose" style={{ minHeight: getDomFullHeight('diagnose', 12) }}>
+    <Card className="diagnose" style={{ minHeight }}>
       <div className={current === 'message' ? 'header-message' : 'header'}>
         <Row gutter={24} style={{ padding: 10, width: '100%' }}>
           {list.map((item: ListProps) => (

+ 2 - 7
src/pages/device/Instance/Detail/Functions/index.tsx

@@ -3,19 +3,14 @@ import { InstanceModel } from '@/pages/device/Instance';
 import type { FunctionMetadata } from '@/pages/device/Product/typings';
 import FnForm from './form';
 import AModel from './AdvancedMode';
-import { getDomFullHeight } from '@/utils/util';
-import { useEffect, useState } from 'react';
 import { Empty } from '@/components';
+import { useDomFullHeight } from '@/hooks';
 
 const Functions = () => {
   const functionList = JSON.parse(InstanceModel.detail.metadata || '{}')
     .functions as FunctionMetadata[];
 
-  const [minHeight, setMinHeight] = useState(100);
-
-  useEffect(() => {
-    setMinHeight(getDomFullHeight('device-detail-function', 12));
-  }, []);
+  const { minHeight } = useDomFullHeight(`.device-detail-function`);
 
   return (
     <Card className={'device-detail-function'} style={{ minHeight: minHeight }}>

+ 3 - 5
src/pages/device/Instance/Detail/Info/index.tsx

@@ -11,19 +11,17 @@ import type { DeviceInstance } from '../../typings';
 import { EditOutlined } from '@ant-design/icons';
 import Tags from '@/pages/device/Instance/Detail/Tags';
 import { PermissionButton } from '@/components';
-import { getDomFullHeight } from '@/utils/util';
+import { useDomFullHeight } from '@/hooks';
 
 const Info = observer(() => {
   const intl = useIntl();
   const [visible, setVisible] = useState<boolean>(false);
   const { permission } = PermissionButton.usePermission('device/Instance');
+  const { minHeight } = useDomFullHeight(`.device-detail-body`);
 
   return (
     <>
-      <Card
-        className={'device-detail-body'}
-        style={{ minHeight: getDomFullHeight('device-detail-body', 12) }}
-      >
+      <Card className={'device-detail-body'} style={{ minHeight }}>
         <Descriptions
           size="small"
           column={3}

+ 3 - 5
src/pages/device/Instance/Detail/Log/index.tsx

@@ -7,13 +7,14 @@ import { useIntl } from '@@/plugin-locale/localeExports';
 import { InstanceModel, service } from '@/pages/device/Instance';
 import { useRef, useState } from 'react';
 import SearchComponent from '@/components/SearchComponent';
-import { getDomFullHeight } from '@/utils/util';
+import { useDomFullHeight } from '@/hooks';
 
 const Log = () => {
   const intl = useIntl();
 
   const actionRef = useRef<ActionType>();
   const [searchParams, setSearchParams] = useState<any>({});
+  const { minHeight } = useDomFullHeight(`.device-detail-log`);
 
   const columns: ProColumns<LogItem>[] = [
     {
@@ -79,10 +80,7 @@ const Log = () => {
   ];
 
   return (
-    <Card
-      className={'device-detail-log'}
-      style={{ minHeight: getDomFullHeight('device-detail-log', 12) }}
-    >
+    <Card className={'device-detail-log'} style={{ minHeight }}>
       <SearchComponent<LogItem>
         field={[...columns]}
         target="logs"

+ 3 - 6
src/pages/device/Instance/Detail/MetadataMap/index.tsx

@@ -6,7 +6,7 @@ import { getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
 import type { ProductItem } from '@/pages/device/Product/typings';
 import { useParams } from 'umi';
 import { PermissionButton, Empty } from '@/components';
-import { getDomFullHeight } from '@/utils/util';
+import { useDomFullHeight } from '@/hooks';
 
 interface Props {
   type: 'device' | 'product';
@@ -18,7 +18,8 @@ const MetadataMap = (props: Props) => {
   const [data, setData] = useState<any>({});
   const params = useParams<{ id: string }>();
   const { permission } = PermissionButton.usePermission('device/Product');
-  const [minHeight, setMinHeight] = useState(300);
+
+  const { minHeight } = useDomFullHeight(`.device-detail-metadataMap`);
 
   const handleSearch = async () => {
     if (props.type === 'product') {
@@ -153,10 +154,6 @@ const MetadataMap = (props: Props) => {
     handleSearch();
   }, [props.type]);
 
-  useEffect(() => {
-    setMinHeight(getDomFullHeight('device-detail-metadataMap', 12));
-  }, []);
-
   return (
     <Card bordered={false} className="device-detail-metadataMap" style={{ minHeight }}>
       {renderComponent()}

+ 4 - 2
src/pages/device/Instance/Detail/Modbus/index.tsx

@@ -17,7 +17,7 @@ import { InstanceModel } from '@/pages/device/Instance';
 import AddPoint from '@/pages/link/Channel/Modbus/Access/addPoint';
 import useSendWebsocketMessage from '@/hooks/websocket/useSendWebsocketMessage';
 import { map } from 'rxjs/operators';
-import { getDomFullHeight } from '@/utils/util';
+import { useDomFullHeight } from '@/hooks';
 
 const Modbus = () => {
   const intl = useIntl();
@@ -37,6 +37,8 @@ const Modbus = () => {
   const wsRef = useRef<any>();
   const [filterList, setFilterList] = useState([]);
 
+  const { minHeight } = useDomFullHeight(`.${styles.list}`);
+
   const columns: ProColumns<any>[] = [
     {
       title: '属性ID',
@@ -211,7 +213,7 @@ const Modbus = () => {
   }, [data]);
 
   return (
-    <Card className={styles.list} style={{ minHeight: getDomFullHeight(styles.list, 12) }}>
+    <Card className={styles.list} style={{ minHeight }}>
       <div style={{ display: 'flex' }}>
         <div>
           <div style={{ width: '250px', marginTop: 15 }}>

+ 4 - 2
src/pages/device/Instance/Detail/Opcua/index.tsx

@@ -17,7 +17,7 @@ import { InstanceModel } from '@/pages/device/Instance';
 import AddPoint from '@/pages/link/Channel/Opcua/Access/addPoint';
 import useSendWebsocketMessage from '@/hooks/websocket/useSendWebsocketMessage';
 import { map } from 'rxjs/operators';
-import { getDomFullHeight } from '@/utils/util';
+import { useDomFullHeight } from '@/hooks';
 
 const Opcua = () => {
   const intl = useIntl();
@@ -39,6 +39,8 @@ const Opcua = () => {
   const wsRef = useRef<any>();
   const [filterList, setFilterList] = useState([]);
 
+  const { minHeight } = useDomFullHeight(`.styles.list`);
+
   const columns: ProColumns<any>[] = [
     {
       title: '属性ID',
@@ -227,7 +229,7 @@ const Opcua = () => {
   }, [data]);
 
   return (
-    <Card className={styles.list} style={{ minHeight: getDomFullHeight(styles.list, 12) }}>
+    <Card className={styles.list} style={{ minHeight }}>
       <div style={{ display: 'flex' }}>
         <div>
           <div style={{ width: '250px', marginTop: 15 }}>

+ 4 - 6
src/pages/device/Product/Detail/index.tsx

@@ -5,7 +5,7 @@ import BaseInfo from '@/pages/device/Product/Detail/BaseInfo';
 import { observer } from '@formily/react';
 import { productModel, service } from '@/pages/device/Product';
 import { useCallback, useEffect, useState } from 'react';
-import { useHistory, useLocation } from '@/hooks';
+import { useDomFullHeight, useHistory, useLocation } from '@/hooks';
 import Metadata from '@/pages/device/components/Metadata';
 import Access from '@/pages/device/Product/Detail/Access';
 import type { DeviceMetadata } from '@/pages/device/Product/typings';
@@ -17,7 +17,6 @@ import MetadataMap from '@/pages/device/Instance/Detail/MetadataMap';
 import SystemConst from '@/utils/const';
 import { PermissionButton } from '@/components';
 import { QuestionCircleOutlined } from '@ant-design/icons';
-import { getDomFullHeight } from '@/utils/util';
 
 export const ModelEnum = {
   base: 'base',
@@ -33,6 +32,8 @@ const ProductDetail = observer(() => {
   const location = useLocation();
   const history = useHistory();
 
+  const { minHeight } = useDomFullHeight('.product-detail-body');
+
   const { permission } = PermissionButton.usePermission('device/Product');
 
   const statusMap = {
@@ -314,10 +315,7 @@ const ProductDetail = observer(() => {
         </PermissionButton>,
       ]}
     >
-      <Card
-        className={'product-detail-body'}
-        style={{ minHeight: getDomFullHeight('product-detail-body', 12) }}
-      >
+      <Card className={'product-detail-body'} style={{ minHeight }}>
         {list.find((k) => k.key === mode)?.component}
         {/* <Tabs
           defaultActiveKey={ModelEnum.base}

+ 4 - 5
src/pages/device/components/Metadata/index.tsx

@@ -14,7 +14,7 @@ import { PermissionButton } from '@/components';
 import { Store } from 'jetlinks-store';
 import SystemConst from '@/utils/const';
 import { useParams } from 'umi';
-import { getDomFullHeight } from '@/utils/util';
+import { useDomFullHeight } from '@/hooks';
 
 interface Props {
   tabAction?: ReactNode;
@@ -31,6 +31,8 @@ const Metadata = observer((props: Props) => {
     props.type === 'device' ? 'device/Instance' : 'device/Product',
   );
 
+  const { minHeight } = useDomFullHeight(`.device-detail-metadata`, 12);
+
   const params = useParams<{ id: string }>();
 
   const resetMetadata = async () => {
@@ -45,10 +47,7 @@ const Metadata = observer((props: Props) => {
   };
 
   return (
-    <div
-      className={'device-detail-metadata'}
-      style={{ position: 'relative', minHeight: getDomFullHeight('device-detail-metadata', 32) }}
-    >
+    <div className={'device-detail-metadata'} style={{ position: 'relative', minHeight }}>
       <div className={styles.tips}>
         <InfoCircleOutlined style={{ marginRight: '3px' }} />
         {InstanceModel.detail?.independentMetadata

+ 4 - 8
src/pages/link/AccessConfig/index.tsx

@@ -9,7 +9,7 @@ import Service from './service';
 import { DeleteOutlined, EditOutlined, PlayCircleOutlined, StopOutlined } from '@ant-design/icons';
 import AccessConfigCard from '@/components/ProTableCard/CardItems/AccessConfig';
 import { PermissionButton, Empty } from '@/components';
-import { getDomFullHeight } from '@/utils/util';
+import { useDomFullHeight } from '@/hooks';
 
 export const service = new Service('gateway/device');
 
@@ -17,7 +17,8 @@ const AccessConfig = () => {
   const history = useHistory();
   const [param, setParam] = useState<any>({ pageSize: 10, terms: [] });
   const { permission } = PermissionButton.usePermission('link/AccessConfig');
-  const [minHeight, setMinHeight] = useState(100);
+
+  const { minHeight } = useDomFullHeight(`.link-accessConfig`);
 
   const columns: ProColumns<any>[] = [
     {
@@ -82,12 +83,7 @@ const AccessConfig = () => {
         }}
       />
       <Card className={'link-accessConfig'} style={{ minHeight }}>
-        <div
-          style={{ width: '100%', display: 'flex', justifyContent: 'flex-start' }}
-          ref={() => {
-            setMinHeight(getDomFullHeight('link-accessConfig'));
-          }}
-        >
+        <div style={{ width: '100%', display: 'flex', justifyContent: 'flex-start' }}>
           <PermissionButton
             isPermission={permission.add}
             onClick={() => {

+ 5 - 8
src/pages/link/Certificate/index.tsx

@@ -1,5 +1,5 @@
 import { PageContainer } from '@ant-design/pro-layout';
-import { useEffect, useRef, useState } from 'react';
+import { useRef, useState } from 'react';
 import type { ActionType, ProColumns } from '@jetlinks/pro-table';
 import ProTable from '@jetlinks/pro-table';
 import { message, Tooltip } from 'antd';
@@ -11,7 +11,7 @@ import usePermissions from '@/hooks/permission';
 import { getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
 import { history } from 'umi';
 import Service from '../service';
-import { getDomFullHeight } from '@/utils/util';
+import { useDomFullHeight } from '@/hooks';
 
 export const service = new Service('network/certificate');
 
@@ -20,7 +20,8 @@ const Certificate = () => {
   const actionRef = useRef<ActionType>();
   const [param, setParam] = useState({});
   const { permission } = usePermissions('link/Certificate');
-  const [minHeight, setMinHeight] = useState(100);
+
+  const { minHeight } = useDomFullHeight(`.link-certificate`, 24);
 
   const columns: ProColumns<CertificateItem>[] = [
     {
@@ -105,10 +106,6 @@ const Certificate = () => {
     },
   ];
 
-  useEffect(() => {
-    setMinHeight(getDomFullHeight('link-certificate', 94));
-  }, []);
-
   return (
     <PageContainer>
       <SearchComponent<CertificateItem>
@@ -126,7 +123,7 @@ const Certificate = () => {
         columns={columns}
         search={false}
         rowKey="id"
-        className={'link-certificate'}
+        tableClassName={'link-certificate'}
         tableStyle={{ minHeight }}
         headerTitle={
           <PermissionButton

+ 3 - 11
src/pages/system/Department/index.tsx

@@ -1,15 +1,15 @@
 // 部门管理
 import { PageContainer } from '@ant-design/pro-layout';
-import { useEffect, useState } from 'react';
+import { useState } from 'react';
 import { Card } from 'antd';
 import Service from '@/pages/system/Department/service';
 import type { DepartmentItem } from '@/pages/system/Department/typings';
 import { observer } from '@formily/react';
 import { model } from '@formily/reactive';
-import { getDomFullHeight } from '@/utils/util';
 import Assets from './Assets';
 import Tree from './Tree';
 import './style';
+import { useDomFullHeight } from '@/hooks';
 
 export const service = new Service('organization');
 
@@ -26,15 +26,7 @@ export const State = model<ModelType>({
 
 export default observer(() => {
   const [parentId, setParentId] = useState('');
-  const [minHeight, setMinHeight] = useState(100);
-
-  useEffect(() => {
-    setTimeout(() => {
-      setMinHeight(getDomFullHeight('department'));
-    }, 0);
-
-    /* eslint-disable */
-  }, []);
+  const { minHeight } = useDomFullHeight(`.department`);
 
   return (
     <PageContainer>