feat : support fixed menu and header (#1260)

* feat: support fixed menu and header

* revert: power by

* fix: designer not work

* fix: cannot scroll

* feat: fixed menu in center

* fix: cannot scroll

* fix: unused
This commit is contained in:
Dunqing 2022-12-18 16:49:50 +08:00 committed by GitHub
parent 6a0b38b7a2
commit 940f5f0152
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 211 additions and 114 deletions

View File

@ -21,7 +21,7 @@
"@formily/react": "2.0.20", "@formily/react": "2.0.20",
"@nocobase/sdk": "0.8.0-alpha.13", "@nocobase/sdk": "0.8.0-alpha.13",
"@nocobase/utils": "0.8.0-alpha.13", "@nocobase/utils": "0.8.0-alpha.13",
"ahooks": "^3.0.5", "ahooks": "^3.7.2",
"antd": "~4.19.5", "antd": "~4.19.5",
"axios": "^0.26.1", "axios": "^0.26.1",
"classnames": "^2.3.1", "classnames": "^2.3.1",

View File

@ -287,9 +287,34 @@ const SettingsCenter = (props) => {
} }
const component = items[pluginName]?.tabs?.[tabName]?.component; const component = items[pluginName]?.tabs?.[tabName]?.component;
return ( return (
<div>
<Layout> <Layout>
<Layout.Sider theme={'light'}> <div
style={
{
'--side-menu-width': '200px',
} as Record<string, string>
}
className={css`
width: var(--side-menu-width);
overflow: hidden;
flex: 0 0 var(--side-menu-width);
max-width: var(--side-menu-width);
min-width: var(--side-menu-width);
pointer-events: none;
`}
></div>
<Layout.Sider
className={css`
height: 100%;
position: fixed;
padding-top: 46px;
left: 0;
top: 0;
background: rgba(0, 0, 0, 0);
z-index: 100;
`}
theme={'light'}
>
<Menu selectedKeys={[pluginName]} style={{ height: 'calc(100vh - 46px)' }}> <Menu selectedKeys={[pluginName]} style={{ height: 'calc(100vh - 46px)' }}>
{Object.keys(items) {Object.keys(items)
.sort() .sort()
@ -331,7 +356,6 @@ const SettingsCenter = (props) => {
<div style={{ margin: 24 }}>{component && React.createElement(component)}</div> <div style={{ margin: 24 }}>{component && React.createElement(component)}</div>
</Layout.Content> </Layout.Content>
</Layout> </Layout>
</div>
); );
}; };

View File

@ -1,6 +1,6 @@
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import { Layout, Spin } from 'antd'; import { Layout, Spin } from 'antd';
import React, { createContext, useContext, useMemo, useRef } from 'react'; import React, { createContext, useContext, useMemo, useRef, useState } from 'react';
import { useHistory, useRouteMatch } from 'react-router-dom'; import { useHistory, useRouteMatch } from 'react-router-dom';
import { import {
ACLAllowConfigure, ACLAllowConfigure,
@ -22,6 +22,7 @@ import {
} from '../../../'; } from '../../../';
import { useCollectionManager } from '../../../collection-manager'; import { useCollectionManager } from '../../../collection-manager';
import { PoweredBy } from '../../../powered-by'; import { PoweredBy } from '../../../powered-by';
import { useMutationObserver } from 'ahooks';
const filterByACL = (schema, options) => { const filterByACL = (schema, options) => {
const { allowAll, allowConfigure, allowMenuItemIds = [] } = options; const { allowAll, allowConfigure, allowMenuItemIds = [] } = options;
@ -123,11 +124,20 @@ const MenuEditor = (props) => {
}; };
const InternalAdminLayout = (props: any) => { const InternalAdminLayout = (props: any) => {
const route = useRoute(); const sideMenuRef = useRef<HTMLDivElement>();
const history = useHistory(); const [sideMenuWidth, setSideMenuWidth] = useState(0);
const match = useRouteMatch<any>();
const { setTitle } = useDocumentTitle(); useMutationObserver(
const sideMenuRef = useRef(); (value) => {
const width = (value[0].target as HTMLDivElement).offsetWidth;
setSideMenuWidth(width);
},
sideMenuRef,
{
childList: true,
attributes: true,
},
);
const result = useSystemSettings(); const result = useSystemSettings();
const { service } = useCollectionManager(); const { service } = useCollectionManager();
@ -142,10 +152,25 @@ const InternalAdminLayout = (props: any) => {
.ant-menu-dark.ant-menu-horizontal > .ant-menu-item:hover { .ant-menu-dark.ant-menu-horizontal > .ant-menu-item:hover {
background-color: rgba(255, 255, 255, 0.1); background-color: rgba(255, 255, 255, 0.1);
} }
position: fixed;
width: 100%;
height: 46px;
line-height: 46px;
padding: 0;
z-index: 100;
`} `}
style={{ height: 46, lineHeight: '46px', position: 'relative', paddingLeft: 0 }}
> >
<div style={{ position: 'relative', zIndex: 1, display: 'flex', height: '100%', width: 'calc(100vw - 300px)' }}> <div
className={css`
position: relative;
width: 100%;
height: 100%;
`}
>
<div
style={{ position: 'relative', zIndex: 1, display: 'flex', height: '100%', width: 'calc(100vw - 300px)' }}
>
<div style={{ width: 200, display: 'inline-flex', color: '#fff', padding: '0', alignItems: 'center' }}> <div style={{ width: 200, display: 'inline-flex', color: '#fff', padding: '0', alignItems: 'center' }}>
<img <img
className={css` className={css`
@ -166,21 +191,51 @@ const InternalAdminLayout = (props: any) => {
<MenuEditor sideMenuRef={sideMenuRef} /> <MenuEditor sideMenuRef={sideMenuRef} />
</div> </div>
</div> </div>
<div style={{ position: 'absolute', zIndex: 10, top: 0, right: 0 }}> <div style={{ position: 'absolute', height: '100%', zIndex: 10, top: 0, right: 0 }}>
<ACLAllowConfigure> <ACLAllowConfigure>
<RemotePluginManagerToolbar /> <RemotePluginManagerToolbar />
</ACLAllowConfigure> </ACLAllowConfigure>
<CurrentUser /> <CurrentUser />
</div> </div>
</div>
</Layout.Header> </Layout.Header>
<Layout> <div
<Layout.Sider style={{ display: 'none' }} theme={'light'} ref={sideMenuRef}></Layout.Sider> style={
{
'--side-menu-width': `${sideMenuWidth}px`,
} as Record<string, string>
}
className={css`
width: var(--side-menu-width);
overflow: hidden;
flex: 0 0 var(--side-menu-width);
max-width: var(--side-menu-width);
min-width: var(--side-menu-width);
pointer-events: none;
transition: background-color 0.3s ease 0s, min-width 0.3s ease 0s,
max-width 0.3s cubic-bezier(0.645, 0.045, 0.355, 1) 0s;
`}
></div>
<Layout.Sider
className={css`
height: 100%;
position: fixed;
padding-top: 46px;
left: 0;
top: 0;
background: rgba(0, 0, 0, 0);
z-index: 100;
`}
style={{ display: 'none' }}
theme={'light'}
ref={sideMenuRef}
></Layout.Sider>
<Layout.Content <Layout.Content
className={css` className={css`
min-height: calc(100vh - 46px);
padding-bottom: 42px;
position: relative; position: relative;
// padding-bottom: 70px; overflow-y: auto;
height: 100vh;
max-height: 100vh;
> div { > div {
position: relative; position: relative;
// z-index: 1; // z-index: 1;
@ -195,13 +250,17 @@ const InternalAdminLayout = (props: any) => {
} }
`} `}
> >
<header
className={css`
height: 46px;
line-height: 46px;
background: transparent;
pointer-events: none;
`}
></header>
{service.contentLoading ? <Spin /> : props.children} {service.contentLoading ? <Spin /> : props.children}
<Layout.Footer>
<PoweredBy />
</Layout.Footer>
</Layout.Content> </Layout.Content>
</Layout> </Layout>
</Layout>
); );
}; };

View File

@ -290,6 +290,7 @@ export const Menu: ComposedMenu = observer((props) => {
onSelect && onSelect(info); onSelect && onSelect(info);
}} }}
className={css` className={css`
height: 100%;
.ant-menu-item { .ant-menu-item {
> .ant-menu-title-content { > .ant-menu-title-content {
margin-left: -24px; margin-left: -24px;

View File

@ -63,6 +63,7 @@ const pageDesignerCss = css`
position: relative; position: relative;
z-index: 20; z-index: 20;
padding-top: 1px; padding-top: 1px;
&:hover { &:hover {
> .general-schema-designer { > .general-schema-designer {
display: block; display: block;

View File

@ -13,6 +13,6 @@
"@emotion/css": "^11.7.1", "@emotion/css": "^11.7.1",
"antd": "~4.19.5", "antd": "~4.19.5",
"sequelize": "^6.9.0", "sequelize": "^6.9.0",
"ahooks": "^3.0.5" "ahooks": "^3.7.2"
} }
} }

View File

@ -5225,6 +5225,11 @@
jest-diff "^26.0.0" jest-diff "^26.0.0"
pretty-format "^26.0.0" pretty-format "^26.0.0"
"@types/js-cookie@^2.x.x":
version "2.2.7"
resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-2.2.7.tgz#226a9e31680835a6188e887f3988e60c04d3f6a3"
integrity sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==
"@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8": "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8":
version "7.0.9" version "7.0.9"
resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d"
@ -6169,14 +6174,21 @@ aggregate-error@^3.0.0:
clean-stack "^2.0.0" clean-stack "^2.0.0"
indent-string "^4.0.0" indent-string "^4.0.0"
ahooks@^3.0.5: ahooks-v3-count@^1.0.0:
version "3.0.5" version "1.0.0"
resolved "https://registry.npmjs.org/ahooks/-/ahooks-3.0.5.tgz#7cf1a057ae147ac02732c3eddb00a793006df9d6" resolved "https://registry.yarnpkg.com/ahooks-v3-count/-/ahooks-v3-count-1.0.0.tgz#ddeb392e009ad6e748905b3cbf63a9fd8262ca80"
integrity sha512-/l8HoNPzJVoexChfw7zlRD1/VyX1X7F08AVNnwkRwgufu1AfUd96XcIStrRsmADqMQWllluLRodEzPbcKUGUzQ== integrity sha512-V7uUvAwnimu6eh/PED4mCDjE7tokeZQLKlxg9lCTMPhN+NjsSbtdacByVlR1oluXQzD3MOw55wylDmQo4+S9ZQ==
ahooks@^3.7.2:
version "3.7.2"
resolved "https://registry.yarnpkg.com/ahooks/-/ahooks-3.7.2.tgz#0afa42625e77ae1cc4b60b19c45cf12a8cf29b56"
integrity sha512-nJPsQJcmJnGaNXiqgZdfO7UMs+o926LQg6VyDYt2vzKhXU8Ze/U87NsA/FeIvlIZB0rQr/j7uotFb1bGPp627A==
dependencies: dependencies:
"@types/js-cookie" "^2.x.x"
ahooks-v3-count "^1.0.0"
dayjs "^1.9.1" dayjs "^1.9.1"
intersection-observer "^0.12.0" intersection-observer "^0.12.0"
js-cookie "^3.0.0" js-cookie "^2.x.x"
lodash "^4.17.21" lodash "^4.17.21"
resize-observer-polyfill "^1.5.1" resize-observer-polyfill "^1.5.1"
screenfull "^5.0.0" screenfull "^5.0.0"
@ -14089,10 +14101,10 @@ js-base64@^2.5.2:
resolved "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4" resolved "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4"
integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ== integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==
js-cookie@^3.0.0: js-cookie@^2.x.x:
version "3.0.1" version "2.2.1"
resolved "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz#9e39b4c6c2f56563708d7d31f6f5f21873a92414" resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8"
integrity sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw== integrity sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==
js-git@^0.7.8: js-git@^0.7.8:
version "0.7.8" version "0.7.8"