fix: 完善右键全屏 (#1572)
Reviewed-on: daoyoucloud/tachybase#1572 Co-authored-by: wjh <wwwjh0710@163.com> Co-committed-by: wjh <wwwjh0710@163.com>
This commit is contained in:
		
							parent
							
								
									5cb9529900
								
							
						
					
					
						commit
						17f9f3b00b
					
				@ -450,7 +450,7 @@ export const InternalAdminLayout = (props: any) => {
 | 
			
		||||
      {params.name && <Layout.Sider className={styles.sider} theme={'light'} ref={sideMenuRef}></Layout.Sider>}
 | 
			
		||||
      <Layout.Content className={styles.main}>
 | 
			
		||||
        <header className={styles.mainHeader}></header>
 | 
			
		||||
        {params.name && pageStyle === 'tab' ? <PageTab /> : <Outlet />}
 | 
			
		||||
        <div className="amplifier-block">{params.name && pageStyle === 'tab' ? <PageTab /> : <Outlet />}</div>
 | 
			
		||||
      </Layout.Content>
 | 
			
		||||
    </Layout>
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,5 @@
 | 
			
		||||
import React, { useRef, useState } from 'react';
 | 
			
		||||
import { uid } from '@tachybase/utils/client';
 | 
			
		||||
 | 
			
		||||
import { css } from '@emotion/css';
 | 
			
		||||
import { App } from 'antd';
 | 
			
		||||
@ -92,56 +93,91 @@ export const disableRightMenu = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const checkedAutoPage = (position, message, t) => {
 | 
			
		||||
  const layoutSider = document.querySelector('.ant-layout-sider');
 | 
			
		||||
  const layoutContent = document.querySelector('.ant-layout-content');
 | 
			
		||||
  const sibling = layoutContent.previousElementSibling;
 | 
			
		||||
  if (!sibling.classList.contains('autoPage')) {
 | 
			
		||||
    const element = document.elementFromPoint(position?.x, position?.y);
 | 
			
		||||
    const blockElement = element.closest('.ant-card');
 | 
			
		||||
    const navbar = document.querySelector('.ant-layout-header');
 | 
			
		||||
    const navbarHeight = navbar.getBoundingClientRect();
 | 
			
		||||
    if (blockElement) {
 | 
			
		||||
      //需要展示的区块
 | 
			
		||||
      const copyBlockElement = blockElement.cloneNode(true);
 | 
			
		||||
      copyBlockElement.style.width = '100%';
 | 
			
		||||
      copyBlockElement.style.height = '90vh';
 | 
			
		||||
      copyBlockElement.style.overflow = 'auto';
 | 
			
		||||
      copyBlockElement.style.backgroundColor = '#ffffff';
 | 
			
		||||
  const element = document.elementFromPoint(position?.x, position?.y);
 | 
			
		||||
  const blockElement = element.closest('.ant-card');
 | 
			
		||||
  const gridRow = blockElement?.closest('.CardRow');
 | 
			
		||||
  const navbar = document.querySelector('.ant-layout-header');
 | 
			
		||||
  const modal = blockElement.closest('.ant-modal-body');
 | 
			
		||||
  const amplifierBlock = blockElement.closest('.amplifier-block');
 | 
			
		||||
  const navbarHeight = navbar.getBoundingClientRect();
 | 
			
		||||
  const classId = uid();
 | 
			
		||||
  if (blockElement) {
 | 
			
		||||
    const page = blockElement?.closest('.ant-nb-page ');
 | 
			
		||||
    const drawer = blockElement?.closest('.ant-drawer-body');
 | 
			
		||||
    const modal = blockElement?.closest('.ant-modal-body');
 | 
			
		||||
    const tabNav = amplifierBlock.querySelector('.ant-tabs-nav');
 | 
			
		||||
    if (tabNav) tabNav.style.display = 'none';
 | 
			
		||||
    const parentNode = gridRow.parentNode;
 | 
			
		||||
    Array.from(parentNode.children).forEach((sibling) => {
 | 
			
		||||
      if (sibling !== gridRow) {
 | 
			
		||||
        sibling.style.display = 'none';
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
    const autoNode = document.createElement('div');
 | 
			
		||||
    autoNode.style.width = amplifierBlock.getBoundingClientRect().width + 'px';
 | 
			
		||||
    autoNode.className = 'autoPage' + classId;
 | 
			
		||||
    autoNode.style.position = 'fixed';
 | 
			
		||||
    autoNode.style.top = '0';
 | 
			
		||||
    autoNode.style.zIndex = '100';
 | 
			
		||||
    //退出按钮
 | 
			
		||||
    const exitNode = document.createElement('div');
 | 
			
		||||
    exitNode.style.width = '100%';
 | 
			
		||||
    exitNode.style.height = '30px';
 | 
			
		||||
    exitNode.style.textAlign = 'center';
 | 
			
		||||
    exitNode.style.lineHeight = '30px';
 | 
			
		||||
    exitNode.style.backgroundColor = '#e6e6e6';
 | 
			
		||||
    exitNode.textContent = `${t('Exit Full Screen')}`;
 | 
			
		||||
    autoNode.appendChild(exitNode);
 | 
			
		||||
    autoNode.addEventListener('click', () => {
 | 
			
		||||
      removeNode({ gridRow, classId });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
      const autoNode = document.createElement('div');
 | 
			
		||||
    if (page) {
 | 
			
		||||
      autoNode.style.marginTop = `${navbarHeight.height}px`;
 | 
			
		||||
      autoNode.style.width = '100%';
 | 
			
		||||
      autoNode.className = 'autoPage';
 | 
			
		||||
      //退出按钮
 | 
			
		||||
      const exitNode = document.createElement('div');
 | 
			
		||||
      exitNode.style.width = '100%';
 | 
			
		||||
      exitNode.style.height = '4vh';
 | 
			
		||||
      exitNode.style.textAlign = 'center';
 | 
			
		||||
      exitNode.style.lineHeight = '4vh';
 | 
			
		||||
      exitNode.style.backgroundColor = '#e6e6e6';
 | 
			
		||||
      exitNode.textContent = `${t('Exit Full Screen')}`;
 | 
			
		||||
      autoNode.appendChild(exitNode);
 | 
			
		||||
      autoNode.appendChild(copyBlockElement);
 | 
			
		||||
      autoNode.addEventListener('click', () => {
 | 
			
		||||
        removeNode(layoutSider);
 | 
			
		||||
      });
 | 
			
		||||
      const fragment = document.createDocumentFragment();
 | 
			
		||||
      fragment.appendChild(autoNode);
 | 
			
		||||
      const header = document.querySelector('.ant-page-header');
 | 
			
		||||
      const layoutSider = document.querySelector('.ant-layout-sider');
 | 
			
		||||
      header.style.display = 'none';
 | 
			
		||||
      layoutSider.style.display = 'none';
 | 
			
		||||
      layoutContent.style.display = 'none';
 | 
			
		||||
      layoutContent?.parentNode.insertBefore(fragment, layoutContent);
 | 
			
		||||
    } else {
 | 
			
		||||
      message.warning(t('There are no full screen blocks available at the current location'));
 | 
			
		||||
      page.style.marginTop = '30px';
 | 
			
		||||
      page.insertAdjacentElement('beforebegin', autoNode);
 | 
			
		||||
    } else if (drawer) {
 | 
			
		||||
      autoNode.style.position = '';
 | 
			
		||||
      drawer.insertAdjacentElement('beforebegin', autoNode);
 | 
			
		||||
    } else if (modal) {
 | 
			
		||||
      autoNode.style.position = '';
 | 
			
		||||
      autoNode.style.width = '100%';
 | 
			
		||||
      modal.insertAdjacentElement('beforebegin', autoNode);
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    removeNode(layoutSider);
 | 
			
		||||
    message.warning(t('There are no full screen blocks available at the current location'));
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const removeNode = (layoutSider) => {
 | 
			
		||||
  const layoutContent = document.querySelector('.ant-layout-content');
 | 
			
		||||
  const sibling = layoutContent.previousElementSibling;
 | 
			
		||||
  layoutSider.style.display = 'block';
 | 
			
		||||
  layoutContent.style.display = 'block';
 | 
			
		||||
  if (sibling.classList.contains('autoPage')) sibling.parentNode.removeChild(sibling);
 | 
			
		||||
const removeNode = ({ gridRow: blockElement, classId }) => {
 | 
			
		||||
  const page = blockElement?.closest('.ant-nb-page ');
 | 
			
		||||
  const drawer = blockElement?.closest('.ant-drawer-body');
 | 
			
		||||
  const parentNode = blockElement.parentNode;
 | 
			
		||||
  const tabNav = document.querySelector('.ant-tabs-nav');
 | 
			
		||||
  if (tabNav) tabNav.style.display = '';
 | 
			
		||||
  Array.from(parentNode.children).forEach((sibling) => {
 | 
			
		||||
    if (sibling !== blockElement) {
 | 
			
		||||
      sibling.style.display = '';
 | 
			
		||||
    }
 | 
			
		||||
    if ((sibling.id as string).includes('DndDescribedBy')) {
 | 
			
		||||
      sibling.style.display = 'none';
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
  if (page) {
 | 
			
		||||
    page.style.marginTop = '';
 | 
			
		||||
    const layoutSider = document.querySelector('.ant-layout-sider');
 | 
			
		||||
    const header = document.querySelector('.ant-page-header');
 | 
			
		||||
    layoutSider.style.display = '';
 | 
			
		||||
    header.style.display = '';
 | 
			
		||||
  } else if (drawer) {
 | 
			
		||||
    drawer.style.marginTop = '';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const autoPage = document.querySelector('.autoPage' + classId);
 | 
			
		||||
 | 
			
		||||
  if (autoPage) autoPage.parentNode.removeChild(autoPage);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,9 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import React, { useState } from 'react';
 | 
			
		||||
import { observer, RecursionField, useField, useFieldSchema } from '@tachybase/schema';
 | 
			
		||||
 | 
			
		||||
import { Drawer } from 'antd';
 | 
			
		||||
import { ArrowsAltOutlined, CloseOutlined, FullscreenExitOutlined, FullscreenOutlined } from '@ant-design/icons';
 | 
			
		||||
import { css } from '@emotion/css';
 | 
			
		||||
import { Button, Drawer } from 'antd';
 | 
			
		||||
import classNames from 'classnames';
 | 
			
		||||
 | 
			
		||||
import { OpenSize } from './';
 | 
			
		||||
@ -61,6 +63,10 @@ export const ActionDrawer: ComposedActionDrawer = observer(
 | 
			
		||||
            </div>
 | 
			
		||||
          )
 | 
			
		||||
        }
 | 
			
		||||
        className={`${props.className} ${css`
 | 
			
		||||
          position: relative;
 | 
			
		||||
          padding-top: 30px;
 | 
			
		||||
        `} amplifier-block`}
 | 
			
		||||
      >
 | 
			
		||||
        <RecursionField
 | 
			
		||||
          basePath={field.address}
 | 
			
		||||
@ -70,6 +76,24 @@ export const ActionDrawer: ComposedActionDrawer = observer(
 | 
			
		||||
            return s['x-component'] !== footerNodeName;
 | 
			
		||||
          }}
 | 
			
		||||
        />
 | 
			
		||||
        <div
 | 
			
		||||
          className={css`
 | 
			
		||||
            position: absolute;
 | 
			
		||||
            top: 0;
 | 
			
		||||
            right: 5px;
 | 
			
		||||
            display: flex;
 | 
			
		||||
          `}
 | 
			
		||||
        >
 | 
			
		||||
          <Amplifier />
 | 
			
		||||
          <Button
 | 
			
		||||
            icon={<CloseOutlined />}
 | 
			
		||||
            className={css`
 | 
			
		||||
              background: none;
 | 
			
		||||
              border: none;
 | 
			
		||||
            `}
 | 
			
		||||
            onClick={() => setVisible(false, true)}
 | 
			
		||||
          />
 | 
			
		||||
        </div>
 | 
			
		||||
      </Drawer>
 | 
			
		||||
    );
 | 
			
		||||
  },
 | 
			
		||||
@ -86,3 +110,27 @@ ActionDrawer.Footer = observer(
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
export default ActionDrawer;
 | 
			
		||||
 | 
			
		||||
export const Amplifier = () => {
 | 
			
		||||
  const [isAmplifier, setIsAmplifier] = useState(false);
 | 
			
		||||
  const [blockWidth, setBlockWidth] = useState('');
 | 
			
		||||
  return (
 | 
			
		||||
    <Button
 | 
			
		||||
      icon={isAmplifier ? <FullscreenExitOutlined /> : <FullscreenOutlined />}
 | 
			
		||||
      className={css`
 | 
			
		||||
        background: none;
 | 
			
		||||
        border: none;
 | 
			
		||||
      `}
 | 
			
		||||
      onClick={(e) => {
 | 
			
		||||
        const element = e.target.closest('.ant-drawer-content-wrapper');
 | 
			
		||||
        if (isAmplifier) {
 | 
			
		||||
          element.style.width = blockWidth;
 | 
			
		||||
        } else {
 | 
			
		||||
          setBlockWidth(element.getBoundingClientRect().width + 'px');
 | 
			
		||||
          element.style.width = '100%';
 | 
			
		||||
        }
 | 
			
		||||
        setIsAmplifier(!isAmplifier);
 | 
			
		||||
      }}
 | 
			
		||||
    />
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,9 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import React, { useState } from 'react';
 | 
			
		||||
import { observer, RecursionField, useField, useFieldSchema } from '@tachybase/schema';
 | 
			
		||||
 | 
			
		||||
import { Modal, ModalProps } from 'antd';
 | 
			
		||||
import { CloseOutlined, FullscreenExitOutlined, FullscreenOutlined } from '@ant-design/icons';
 | 
			
		||||
import { css } from '@emotion/css';
 | 
			
		||||
import { Button, Modal, ModalProps } from 'antd';
 | 
			
		||||
import { createStyles } from 'antd-style';
 | 
			
		||||
import classNames from 'classnames';
 | 
			
		||||
 | 
			
		||||
@ -61,8 +63,18 @@ export const ActionModal: ComposedActionDrawer<ModalProps> = observer(
 | 
			
		||||
        }}
 | 
			
		||||
        destroyOnClose
 | 
			
		||||
        open={visible}
 | 
			
		||||
        onCancel={() => setVisible(false, true)}
 | 
			
		||||
        className={classNames(others.className, modalProps?.className, styles.container)}
 | 
			
		||||
        closable={false}
 | 
			
		||||
        className={classNames(
 | 
			
		||||
          others.className,
 | 
			
		||||
          modalProps?.className,
 | 
			
		||||
          styles.container,
 | 
			
		||||
          'amplifier-block',
 | 
			
		||||
          css`
 | 
			
		||||
            .ant-modal-content {
 | 
			
		||||
              padding-top: 32px;
 | 
			
		||||
            }
 | 
			
		||||
          `,
 | 
			
		||||
        )}
 | 
			
		||||
        footer={
 | 
			
		||||
          footerSchema ? (
 | 
			
		||||
            <RecursionField
 | 
			
		||||
@ -86,6 +98,24 @@ export const ActionModal: ComposedActionDrawer<ModalProps> = observer(
 | 
			
		||||
            return s['x-component'] !== footerNodeName;
 | 
			
		||||
          }}
 | 
			
		||||
        />
 | 
			
		||||
        <div
 | 
			
		||||
          className={css`
 | 
			
		||||
            position: absolute;
 | 
			
		||||
            top: 0;
 | 
			
		||||
            right: 5px;
 | 
			
		||||
            display: flex;
 | 
			
		||||
          `}
 | 
			
		||||
        >
 | 
			
		||||
          <Amplifier />
 | 
			
		||||
          <Button
 | 
			
		||||
            icon={<CloseOutlined />}
 | 
			
		||||
            className={css`
 | 
			
		||||
              background: none;
 | 
			
		||||
              border: none;
 | 
			
		||||
            `}
 | 
			
		||||
            onClick={() => setVisible(false, true)}
 | 
			
		||||
          />
 | 
			
		||||
        </div>
 | 
			
		||||
      </Modal>
 | 
			
		||||
    );
 | 
			
		||||
  },
 | 
			
		||||
@ -102,3 +132,39 @@ ActionModal.Footer = observer(
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
export default ActionModal;
 | 
			
		||||
 | 
			
		||||
export const Amplifier = () => {
 | 
			
		||||
  const [isAmplifier, setIsAmplifier] = useState(false);
 | 
			
		||||
  const [blockWidth, setBlockWidth] = useState('');
 | 
			
		||||
  return (
 | 
			
		||||
    <Button
 | 
			
		||||
      icon={isAmplifier ? <FullscreenExitOutlined /> : <FullscreenOutlined />}
 | 
			
		||||
      className={css`
 | 
			
		||||
        background: none;
 | 
			
		||||
        border: none;
 | 
			
		||||
      `}
 | 
			
		||||
      onClick={(e) => {
 | 
			
		||||
        const element = e.target.closest('.ant-modal-content');
 | 
			
		||||
        const modal = document.querySelector('.ant-modal');
 | 
			
		||||
        const mask = document.querySelector('.ant-modal-mask');
 | 
			
		||||
        if (isAmplifier) {
 | 
			
		||||
          modal.style.width = blockWidth;
 | 
			
		||||
          element.style.width = '';
 | 
			
		||||
          modal.style.top = '';
 | 
			
		||||
          modal.style.padding = '';
 | 
			
		||||
          modal.style.margin = '';
 | 
			
		||||
          mask.style.backgroundColor = '';
 | 
			
		||||
        } else {
 | 
			
		||||
          setBlockWidth(modal.getBoundingClientRect().width + 'px');
 | 
			
		||||
          element.style.width = '100vw';
 | 
			
		||||
          modal.style.width = '100%';
 | 
			
		||||
          modal.style.top = '0';
 | 
			
		||||
          modal.style.padding = '0';
 | 
			
		||||
          modal.style.margin = '0';
 | 
			
		||||
          mask.style.backgroundColor = '#f3f3f3';
 | 
			
		||||
        }
 | 
			
		||||
        setIsAmplifier(!isAmplifier);
 | 
			
		||||
      }}
 | 
			
		||||
    />
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -57,6 +57,7 @@ export const ActionSheet: ComposedActionDrawer = observer(
 | 
			
		||||
            </Button>
 | 
			
		||||
          </Space>
 | 
			
		||||
        }
 | 
			
		||||
        className={`${props.className} amplifier-block`}
 | 
			
		||||
      >
 | 
			
		||||
        <RecursionField
 | 
			
		||||
          basePath={field.address}
 | 
			
		||||
 | 
			
		||||
@ -504,7 +504,7 @@ Grid.Col = observer(
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
      <GridColContext.Provider value={{ cols, schema }}>
 | 
			
		||||
        <div ref={setNodeRef} style={{ ...style, ...droppableStyle }} className={cls('nb-grid-col')}>
 | 
			
		||||
        <div ref={setNodeRef} style={{ ...style, ...droppableStyle }} className={cls('nb-grid-col  CardCol')}>
 | 
			
		||||
          {props.children}
 | 
			
		||||
        </div>
 | 
			
		||||
      </GridColContext.Provider>
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user