Browse Source

完善布局调整

main
dark 3 months ago
parent
commit
96e9dac0ca
  1. 67
      src/hooks/useScrollMask.ts
  2. 47
      src/hooks/useScrollStyle.ts
  3. 5
      src/layout/TwoColPageLayout.tsx
  4. 4
      src/layout/style.ts
  5. 2
      src/pages/system/menus/index.tsx
  6. 12
      src/pages/system/menus/style.ts

67
src/hooks/useScrollMask.ts

@ -0,0 +1,67 @@
import { useEffect } from 'react'
type Ref = { current: Element }
const useScrollMask = (ref: Ref | string) => {
useEffect(() => {
let element: Ref
if (typeof ref === 'string') {
element = {
current: document.querySelector(ref)!
}
if (!element.current) return
} else {
element = ref as Ref
}
if (!element.current) return
const handleScroll = () => {
const { scrollTop, scrollHeight, clientHeight } = element.current
const atTop = scrollTop === 0
const atBottom = scrollTop + clientHeight === scrollHeight
if (atTop && atBottom) {
element.current.setAttribute('data-top-bottom-scroll', 'true')
element.current.removeAttribute('data-top-scroll')
element.current.removeAttribute('data-bottom-scroll')
} else if (atTop) {
element.current.setAttribute('data-top-scroll', 'true')
element.current.removeAttribute('data-bottom-scroll')
element.current.removeAttribute('data-top-bottom-scroll')
} else if (atBottom) {
element.current.setAttribute('data-bottom-scroll', 'true')
element.current.removeAttribute('data-top-scroll')
element.current.removeAttribute('data-top-bottom-scroll')
} else {
element.current.setAttribute('data-top-bottom-scroll', 'true')
element.current.removeAttribute('data-bottom-scroll')
element.current.removeAttribute('data-top-scroll')
}
}
const checkScroll = () => {
const hasVerticalScrollbar = element.current.scrollHeight > element.current.clientHeight
if (hasVerticalScrollbar) {
element.current.classList.add('scroll-mask')
} else {
element.current.classList.remove('scroll-mask')
}
handleScroll() // Initial check
}
element.current.addEventListener('scroll', handleScroll)
window.addEventListener('resize', checkScroll)
checkScroll()
return () => {
element.current.removeEventListener('scroll', handleScroll)
window.removeEventListener('resize', checkScroll)
}
}, [ ref ])
}
export default useScrollMask

47
src/hooks/useScrollStyle.ts

@ -114,10 +114,57 @@ export const useScrollStyle = () => {
${darkScrollbar} ${darkScrollbar}
`; `;
const scrollbar1 = css `
/* 通用的 overflow 和 padding */
.scroll-mask {
--scroll-shadow-size: 40px;
overflow-y: auto;
margin-right: -1.5rem; /* -mr-6 */
height: 100%; /* h-full */
max-height: 100%; /* max-h-full */
padding-top: 1.5rem; /* py-6 */
padding-bottom: 1.5rem; /* py-6 */
padding-right: 1.5rem; /* pr-6 */
}
/* 顶部遮罩效果 */
.scroll-mask-top {
mask-image: linear-gradient(0deg, #000 calc(100% - var(--scroll-shadow-size)), transparent);
}
/* 底部遮罩效果 */
.scroll-mask-bottom {
mask-image: linear-gradient(180deg, #000 calc(100% - var(--scroll-shadow-size)), transparent);
}
/* 顶部和底部遮罩效果 */
.scroll-mask-top-bottom {
mask-image: linear-gradient(#000, #000, transparent 0, #000 var(--scroll-shadow-size), #000 calc(100% - var(--scroll-shadow-size)), transparent);
}
/* 根据滚动状态动态应用遮罩效果 */
[data-top-scroll="true"] {
mask-image: linear-gradient(0deg, #000 calc(100% - var(--scroll-shadow-size)), transparent);
}
[data-bottom-scroll="true"] {
mask-image: linear-gradient(180deg, #000 calc(100% - var(--scroll-shadow-size)), transparent);
}
[data-top-bottom-scroll="true"] {
mask-image: linear-gradient(#000, #000, transparent 0, #000 var(--scroll-shadow-size), #000 calc(100% - var(--scroll-shadow-size)), transparent);
}
`
return { return {
scrollbarBackground, scrollbarBackground,
scrollbar, scrollbar,
darkScrollbarBackground, darkScrollbarBackground,
darkScrollbar, darkScrollbar,
scrollbar1,
} }
} }

5
src/layout/TwoColPageLayout.tsx

@ -9,14 +9,15 @@ interface ITreePageLayoutProps {
draggableProps?: DraggablePanelProps draggableProps?: DraggablePanelProps
pageProps?: PageContainerProps pageProps?: PageContainerProps
leftPanel?: React.ReactNode leftPanel?: React.ReactNode
className?: string
} }
export const TwoColPageLayout: React.FC<ITreePageLayoutProps> = (props) => {
export const TwoColPageLayout: React.FC<ITreePageLayoutProps> = ({ className, ...props }) => {
const { styles, cx } = useStyle({ className: 'two-col' }) const { styles, cx } = useStyle({ className: 'two-col' })
return ( return (
<PageContainer <PageContainer
breadcrumbRender={false} title={false} breadcrumbRender={false} title={false}
className={cx( styles.pageCard)}
className={cx(styles.pageCard, styles.layoutTable, className)}
{...props.pageProps} {...props.pageProps}
> >
<Flexbox horizontal className={styles.authHeight}> <Flexbox horizontal className={styles.authHeight}>

4
src/layout/style.ts

@ -48,8 +48,8 @@ export const useStyle = createStyles(({ token, css, cx, prefixCls }, props: any)
.ant-pro-card-body{ .ant-pro-card-body{
padding-block-start: 0; padding-block-start: 0;
overflow: auto; overflow: auto;
height: calc(100vh - 100px);
min-height: calc(100vh - 100px);
height: calc(100vh - 110px);
min-height: calc(100vh - 110px);
${scrollbarBackground} ${scrollbarBackground}
} }

2
src/pages/system/menus/index.tsx

@ -24,6 +24,7 @@ const Menus = () => {
const [ currentMenu, setMenuData ] = useAtom<MenuItem>(selectedMenuAtom) ?? {} const [ currentMenu, setMenuData ] = useAtom<MenuItem>(selectedMenuAtom) ?? {}
const menuInputRef = useRef<InputRef | undefined>(undefined) const menuInputRef = useRef<InputRef | undefined>(undefined)
useEffect(() => { useEffect(() => {
if (isError) { if (isError) {
@ -42,6 +43,7 @@ const Menus = () => {
return ( return (
<TwoColPageLayout <TwoColPageLayout
className={styles.container}
leftPanel={<> leftPanel={<>
<ProCard title={t('system.menus.title', '菜单')} <ProCard title={t('system.menus.title', '菜单')}
extra={ extra={

12
src/pages/system/menus/style.ts

@ -3,12 +3,18 @@ import { useScrollStyle } from '@/hooks/useScrollStyle'
export const useStyle = createStyles(({ token, css, cx, prefixCls }) => { export const useStyle = createStyles(({ token, css, cx, prefixCls }) => {
const prefix = `${prefixCls}-${token?.proPrefix}-menu-page` const prefix = `${prefixCls}-${token?.proPrefix}-menu-page`
const { scrollbarBackground } = useScrollStyle()
const { scrollbarBackground, scrollbar1 } = useScrollStyle()
const container = css`
${scrollbar1}
`
const box = css` const box = css`
flex: 1; flex: 1;
background: ${token.colorBgContainer}; background: ${token.colorBgContainer};
` `
const emptyForm = css` const emptyForm = css`
` `
@ -33,7 +39,7 @@ export const useStyle = createStyles(({ token, css, cx, prefixCls }) => {
const formButtons = css` const formButtons = css`
width: 500px; width: 500px;
.ant-pro-card-body { .ant-pro-card-body {
overflow: hidden;
//overflow: hidden;
} }
` `
@ -81,7 +87,7 @@ export const useStyle = createStyles(({ token, css, cx, prefixCls }) => {
` `
return { return {
container: cx(prefix),
container: cx(prefix, container),
box, box,
emptyForm, emptyForm,
tree, tree,

Loading…
Cancel
Save