diff --git a/packages/core/client/src/modules/popup/__e2e__/schemaInitializer1.test.ts b/packages/core/client/src/modules/popup/__e2e__/schemaInitializer1.test.ts index 94561bb6a3..7d9b481842 100644 --- a/packages/core/client/src/modules/popup/__e2e__/schemaInitializer1.test.ts +++ b/packages/core/client/src/modules/popup/__e2e__/schemaInitializer1.test.ts @@ -34,6 +34,7 @@ test.describe('where to open a popup and what can be added to it', () => { // add blocks await page.getByLabel('schema-initializer-Grid-popup:addNew:addBlock-general').hover(); await page.getByText('Markdown').click(); + await page.waitForTimeout(500); await page.getByLabel('schema-initializer-Grid-popup:addNew:addBlock-general').hover(); await page.getByText('Form').hover(); await page.getByRole('menuitem', { name: 'Current collection' }).click(); diff --git a/packages/core/client/src/schema-component/antd/association-field/InternalNester.tsx b/packages/core/client/src/schema-component/antd/association-field/InternalNester.tsx index 0483d86cc8..dff712bf09 100644 --- a/packages/core/client/src/schema-component/antd/association-field/InternalNester.tsx +++ b/packages/core/client/src/schema-component/antd/association-field/InternalNester.tsx @@ -18,24 +18,12 @@ import { NocoBaseRecursionField } from '../../../formily/NocoBaseRecursionField' import { useAssociationFieldContext, useInsertSchema } from './hooks'; import schema from './schema'; -const InternalNesterCss = css` - & .ant-formily-item-layout-vertical { - margin-bottom: 10px; - } - .ant-card-body { - padding: 15px 20px 5px; - } - .ant-divider-horizontal { - margin: 10px 0; - } -`; - const InternalNesterCardCss = css` .ant-card-bordered { border: none; } .ant-card-body { - padding: 0px 20px 20px 0px; + padding: 0px 20px 0px 0px; } `; @@ -55,6 +43,20 @@ export const InternalNester = observer( labelWrap = true, } = fieldSchema?.['x-component-props'] || {}; + const InternalNesterCss = css` + margin-top: 0.4em; + + & .ant-formily-item-layout-vertical { + margin-bottom: 10px; + } + .ant-card-body { + padding: ${token.padding}px ${token.paddingLG}px; + } + .ant-divider-horizontal { + margin: 10px 0; + } + `; + useEffect(() => { insertNester(schema.Nester); }, []); diff --git a/packages/core/client/src/schema-component/antd/grid-card/GridCard.Decorator.style.ts b/packages/core/client/src/schema-component/antd/grid-card/GridCard.Decorator.style.ts index dd641ed636..e3ff692660 100644 --- a/packages/core/client/src/schema-component/antd/grid-card/GridCard.Decorator.style.ts +++ b/packages/core/client/src/schema-component/antd/grid-card/GridCard.Decorator.style.ts @@ -11,8 +11,19 @@ import { genStyleHook } from '../__builtins__'; const useStyles = genStyleHook('nb-grid-card', (token) => { const { componentCls } = token; + return { [componentCls]: { + '.nb-action-bar': { + borderRadius: token.borderRadiusBlock, + marginBottom: `${token.marginBlock / 2}px !important`, + }, + + '.ant-list-pagination': { + borderRadius: token.borderRadiusBlock, + marginTop: `${token.marginBlock / 2}px !important`, + }, + '& > .nb-block-item': { marginBottom: token.marginLG, '& > .nb-action-bar:has(:first-child:not(:empty))': { diff --git a/packages/core/client/src/schema-component/antd/grid-card/GridCard.Item.tsx b/packages/core/client/src/schema-component/antd/grid-card/GridCard.Item.tsx index 1bcba0f03a..25a946e6b0 100644 --- a/packages/core/client/src/schema-component/antd/grid-card/GridCard.Item.tsx +++ b/packages/core/client/src/schema-component/antd/grid-card/GridCard.Item.tsx @@ -28,15 +28,10 @@ const itemCss = css` const gridCardCss = css` height: 100%; > .ant-card-body { - padding: 24px 24px 0px; height: 100%; - button { - margin-bottom: 0px !important; - margin-top: 5px; - } } .nb-action-bar { - padding: 5px 0; + padding-top: 5px; } `; diff --git a/packages/core/client/src/schema-component/antd/grid-card/GridCard.tsx b/packages/core/client/src/schema-component/antd/grid-card/GridCard.tsx index c9d385dd09..0ad8a32745 100644 --- a/packages/core/client/src/schema-component/antd/grid-card/GridCard.tsx +++ b/packages/core/client/src/schema-component/antd/grid-card/GridCard.tsx @@ -17,6 +17,7 @@ import { getCardItemSchema } from '../../../block-provider'; import { NocoBaseRecursionField } from '../../../formily/NocoBaseRecursionField'; import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps'; import { withSkeletonComponent } from '../../../hoc/withSkeletonComponent'; +import { useToken } from '../../../style/useToken'; import { SortableItem } from '../../common'; import { SchemaComponentOptions } from '../../core'; import { useDesigner, useProps } from '../../hooks'; @@ -141,6 +142,7 @@ const InternalGridCard = withSkeletonComponent( }, [fieldSchema.properties], ); + const { token } = useToken(); const onPaginationChange: PaginationProps['onChange'] = useCallback( (page, pageSize) => { @@ -207,7 +209,7 @@ const InternalGridCard = withSkeletonComponent( ...columnCount, sm: columnCount.xs, xl: columnCount.lg, - gutter: [rowGutter, rowGutter], + gutter: [token.marginBlock / 2, token.marginBlock / 2], }} renderItem={(item, index) => { return ( diff --git a/packages/plugins/@nocobase/plugin-block-workbench/src/client/WorkbenchAction.tsx b/packages/plugins/@nocobase/plugin-block-workbench/src/client/WorkbenchAction.tsx index 889dda2bc0..1b58c9b1f1 100644 --- a/packages/plugins/@nocobase/plugin-block-workbench/src/client/WorkbenchAction.tsx +++ b/packages/plugins/@nocobase/plugin-block-workbench/src/client/WorkbenchAction.tsx @@ -18,13 +18,20 @@ import { WorkbenchLayout } from './workbenchBlockSettings'; const useStyles = createStyles(({ token, css }) => ({ // 支持 css object 的写法 action: css` + display: flex; background-color: transparent; border: 0; height: auto; box-shadow: none; + padding-top: 8px; + `, + avatar: css` + width: 4em; `, title: css` margin-top: ${token.marginSM}px; + width: 100%; + white-space: nowrap; text-overflow: ellipsis; overflow: hidden; `, @@ -37,8 +44,8 @@ function Button() { const { layout } = useContext(WorkbenchBlockContext); const { styles, cx } = useStyles(); return layout === WorkbenchLayout.Grid ? ( -
- } /> +
+ } />
{fieldSchema.title}
) : ( @@ -55,6 +62,7 @@ export const WorkbenchAction = withDynamicSchemaProps((props) => { } confirmTitle={fieldSchema.title} diff --git a/packages/plugins/@nocobase/plugin-block-workbench/src/client/WorkbenchBlock.tsx b/packages/plugins/@nocobase/plugin-block-workbench/src/client/WorkbenchBlock.tsx index 697e34e735..e56de6da59 100644 --- a/packages/plugins/@nocobase/plugin-block-workbench/src/client/WorkbenchBlock.tsx +++ b/packages/plugins/@nocobase/plugin-block-workbench/src/client/WorkbenchBlock.tsx @@ -7,23 +7,22 @@ * For more information, please refer to: https://www.nocobase.com/agreement. */ -import { css } from '@emotion/css'; import { observer, useFieldSchema } from '@formily/react'; import { CollectionContext, + createStyles, DataSourceContext, DndContext, Icon, NocoBaseRecursionField, - useBlockHeight, useDesignable, + useOpenModeContext, useSchemaInitializerRender, withDynamicSchemaProps, - useOpenModeContext, - useBlockHeightProps, } from '@nocobase/client'; -import { Space, List, Avatar, theme } from 'antd'; -import React, { createContext, useEffect, useState, useRef, useMemo, useLayoutEffect } from 'react'; +import { Avatar, Space } from 'antd'; +import { Grid, List } from 'antd-mobile'; +import React, { createContext } from 'react'; import { WorkbenchLayout } from './workbenchBlockSettings'; const ConfigureActionsButton = observer( @@ -45,105 +44,27 @@ const ResponsiveSpace = () => { const isMobileMedia = isMobile(); const { isMobile: underMobileCtx } = useOpenModeContext() || {}; const { itemsPerRow = 4 } = fieldSchema.parent['x-decorator-props'] || {}; - const isUnderMobile = isMobileMedia || underMobileCtx; - const containerRef = useRef(null); // 引用容器 - const [containerWidth, setContainerWidth] = useState(0); // 容器宽度 - // 使用 ResizeObserver 动态获取容器宽度 - useEffect(() => { - const handleResize = () => { - if (containerRef.current) { - setContainerWidth(containerRef.current.offsetWidth); // 更新宽度 - } - }; - // 初始化 ResizeObserver - const resizeObserver = new ResizeObserver(handleResize); - // 监听容器宽度变化 - if (containerRef.current) { - resizeObserver.observe(containerRef.current); - handleResize(); // 初始化时获取一次宽度 - } - - return () => { - if (containerRef.current) { - resizeObserver.unobserve(containerRef.current); - } - }; - }, []); - - useLayoutEffect(() => { - if (!containerRef.current) return; - - const observer = new ResizeObserver((entries) => { - for (const entry of entries) { - setContainerWidth(entry.contentRect.width); // 更新宽度 - } - }); - - observer.observe(containerRef.current); - - return () => { - observer.unobserve(containerRef.current); - }; - }, []); - - // 计算每个元素的宽度 - const itemWidth = useMemo(() => { - if (isUnderMobile) { - const totalGapWidth = gap * itemsPerRow; - const availableWidth = containerWidth - totalGapWidth; - return availableWidth / itemsPerRow; - } - return 70; - }, [itemsPerRow, gap, containerWidth]); - - // 计算 Avatar 的宽度 - const avatarSize = useMemo(() => { - return isUnderMobile ? (Math.floor(itemWidth * 0.8) > 70 ? 60 : Math.floor(itemWidth * 0.8)) : 54; // Avatar 大小为 item 宽度的 60% - }, [itemWidth, itemsPerRow, containerWidth]); + if (underMobileCtx || isMobileMedia) { + return ( + + {fieldSchema.mapProperties((s, key) => { + return ( + + + + ); + })} + + ); + } return ( -
- - {fieldSchema.mapProperties((s, key) => ( -
- -
- ))} -
-
+ + {fieldSchema.mapProperties((s, key) => { + return ; + })} + ); }; @@ -157,36 +78,17 @@ const InternalIcons = () => { {layout === WorkbenchLayout.Grid ? ( ) : ( - + {fieldSchema.mapProperties((s, key) => { const icon = s['x-component-props']?.['icon']; const backgroundColor = s['x-component-props']?.['iconColor']; return ( } />} + onClick={() => {}} > - } />} - title={} - > + ); })} @@ -199,44 +101,55 @@ const InternalIcons = () => { export const WorkbenchBlockContext = createContext({ layout: 'grid' }); +const useStyles = createStyles(({ token, css }) => ({ + containerClass: css` + &.list { + margin: -${token.paddingLG}px; + border-radius: ${(token as any).borderRadiusBlock}px; + overflow: hidden; + + .adm-list { + --padding-left: ${token.paddingLG}px; + --padding-right: ${token.paddingLG}px; + + .adm-list-item-content-main { + display: flex; + + button { + background-color: transparent; + border: none; + height: auto; + box-shadow: none; + padding: 16px 32px; + margin: -12px -32px; + width: calc(100% + 64px); + text-align: start; + color: ${token.colorText}; + } + } + } + + button[aria-label*='schema-initializer-WorkbenchBlock.ActionBar-workbench:configureActions'] { + margin-bottom: ${token.paddingLG}px; + margin-left: ${token.paddingLG}px; + } + } + `, +})); + export const WorkbenchBlock: any = withDynamicSchemaProps( (props) => { const fieldSchema = useFieldSchema(); const { layout = 'grid' } = fieldSchema['x-component-props'] || {}; - const { title } = fieldSchema['x-decorator-props'] || {}; - const targetHeight = useBlockHeight(); - const { token } = theme.useToken(); - const { designable } = useDesignable(); - const titleHeight = title ? token.fontSizeLG * token.lineHeightLG + token.padding * 2 - 1 : 0; - const internalHeight = 2 * token.paddingLG + token.controlHeight + token.marginLG + titleHeight; - const warperHeight = - targetHeight - (designable ? internalHeight : 2 * token.paddingLG + token.marginLG + titleHeight); - const targetWarperHeight = warperHeight > 0 ? warperHeight + 'px' : '100%'; + const { styles } = useStyles(); + return ( -
-
- - - {props.children} - - -
+
+ + + {props.children} + +
); }, diff --git a/packages/plugins/@nocobase/plugin-mobile/src/client/__e2e__/zIndex.test.ts b/packages/plugins/@nocobase/plugin-mobile/src/client/__e2e__/zIndex.test.ts index c7b1b58bc8..74e3208e35 100644 --- a/packages/plugins/@nocobase/plugin-mobile/src/client/__e2e__/zIndex.test.ts +++ b/packages/plugins/@nocobase/plugin-mobile/src/client/__e2e__/zIndex.test.ts @@ -56,14 +56,27 @@ test.describe('zIndex', () => { await page.getByLabel('Close lightbox').click(); // 3. 进入第二层子页面,然后点击图片预览, 图片不能被子页面盖住 - await page.getByLabel('action-Action-Edit-update-').click(); + await page.getByLabel('action-Action-Edit-update-').click({ + position: { + x: 5, + y: 5, + }, + }); await page.getByRole('link', { name: title }).nth(2).click(); await page.waitForTimeout(300); await check(2); await page.getByLabel('Close lightbox').click(); // 4. 进入第三层子页面,然后点击图片预览, 图片不能被子页面盖住 - await page.getByLabel('action-Action-Edit-update-').nth(2).click(); + await page + .getByLabel('action-Action-Edit-update-') + .nth(2) + .click({ + position: { + x: 5, + y: 5, + }, + }); await page.getByRole('link', { name: title }).nth(3).click(); await page.waitForTimeout(300); await check(3); diff --git a/packages/plugins/@nocobase/plugin-mobile/src/client/mobile-blocks/settings-block/MobileSettings.tsx b/packages/plugins/@nocobase/plugin-mobile/src/client/mobile-blocks/settings-block/MobileSettings.tsx index bf5e00692a..c7d734fed7 100644 --- a/packages/plugins/@nocobase/plugin-mobile/src/client/mobile-blocks/settings-block/MobileSettings.tsx +++ b/packages/plugins/@nocobase/plugin-mobile/src/client/mobile-blocks/settings-block/MobileSettings.tsx @@ -16,8 +16,10 @@ export const InternalSettings = () => { const style = useMemo(() => { return { marginBottom: token.marginBlock, + borderRadius: token.borderRadiusBlock, + overflow: 'hidden', }; - }, [token.marginBlock]); + }, [token.borderRadiusBlock, token.marginBlock]); return ( diff --git a/packages/plugins/@nocobase/plugin-mobile/src/client/mobile/Mobile.tsx b/packages/plugins/@nocobase/plugin-mobile/src/client/mobile/Mobile.tsx index 62b2600862..5e99193c84 100644 --- a/packages/plugins/@nocobase/plugin-mobile/src/client/mobile/Mobile.tsx +++ b/packages/plugins/@nocobase/plugin-mobile/src/client/mobile/Mobile.tsx @@ -23,6 +23,7 @@ import { import React from 'react'; import { isDesktop } from 'react-device-detect'; +import { theme } from 'antd'; import { ActionDrawerUsedInMobile, useToAdaptActionDrawerToMobile } from '../adaptor-of-desktop/ActionDrawer'; import { useToAdaptFilterActionToMobile } from '../adaptor-of-desktop/FilterAction'; import { InternalPopoverNesterUsedInMobile } from '../adaptor-of-desktop/InternalPopoverNester'; @@ -92,11 +93,13 @@ export const Mobile = () => { diff --git a/packages/plugins/@nocobase/plugin-mobile/src/client/mobile/styles.ts b/packages/plugins/@nocobase/plugin-mobile/src/client/mobile/styles.ts index e43e31397e..daf87c36ca 100644 --- a/packages/plugins/@nocobase/plugin-mobile/src/client/mobile/styles.ts +++ b/packages/plugins/@nocobase/plugin-mobile/src/client/mobile/styles.ts @@ -8,43 +8,30 @@ */ import { genStyleHook } from '@nocobase/client'; -import { PageBackgroundColor } from '../constants'; export const useStyles = genStyleHook('nb-mobile', (token) => { const { componentCls } = token; return { [componentCls]: { + // 调整移动端 Grid card 区块顶部按钮和卡片之间的间距 + '--nb-spacing': '12px', + WebkitOverflowScrolling: 'touch', display: 'initial', '& ::-webkit-scrollbar': { display: 'none', }, - body: { - backgroundColor: PageBackgroundColor, - }, '.nb-details .ant-formily-item-feedback-layout-loose': { marginBottom: '5px', }, '.nb-details .ant-formily-item-layout-vertical .ant-formily-item-label': { marginBottom: '-8px', }, - '.ant-card .ant-card-body': { - paddingBottom: '10px', - paddingTop: '10px', - }, '.ant-pagination-simple': { marginTop: '0px !important', }, - '.nb-action-penal-container': { - marginTop: '-10px', - marginBottom: '-10px', - }, - '.nb-action-penal-container button[aria-label*="schema-initializer-WorkbenchBlock.ActionBar-workbench:configureActions"]': - { - marginBottom: '10px', - }, '.ant-list-item': { paddingTop: '8px', paddingBottom: '8px', @@ -58,9 +45,6 @@ export const useStyles = genStyleHook('nb-mobile', (token) => { paddingBottom: '0px', paddingTop: '0px', }, - '.nb-chart-block .noco-card-item': { - marginBottom: '-13px', - }, '.ant-table-thead button[aria-label*="schema-initializer-TableV2-table:configureColumns"] > span:last-child': { display: 'none !important', }, @@ -87,22 +71,6 @@ export const useStyles = genStyleHook('nb-mobile', (token) => { '.ant-pagination .ant-pagination-item': { display: 'none', }, - '.ant-card-body .nb-action-bar .ant-btn': { - justifyContent: 'space-between', - display: 'flex', - alignItems: 'center', - gap: '8px', - '& span': { - display: 'contents', - }, - }, - '.ant-card-body .nb-action-bar .ant-btn-icon': { - marginInlineEnd: '0px !important', - }, - '.ant-card-body .nb-table-container': { - marginRight: '-20px', - marginLeft: '-10px', - }, '.nb-action-bar button[aria-label*="schema-initializer-ActionBar-table:configureActions"] > span:last-child': { display: 'none !important', }, @@ -121,6 +89,11 @@ export const useStyles = genStyleHook('nb-mobile', (token) => { '[data-menu-id$="-theme"]': { display: 'none', }, + + '& > .ant-menu > .ant-menu-item': { + marginInline: 8, + width: `calc(100% - 16px)`, + }, }, }, }; diff --git a/packages/plugins/@nocobase/plugin-mobile/src/client/pages/dynamic-page/content/MobilePageContentContainer.tsx b/packages/plugins/@nocobase/plugin-mobile/src/client/pages/dynamic-page/content/MobilePageContentContainer.tsx index b474e08622..1285cf538a 100644 --- a/packages/plugins/@nocobase/plugin-mobile/src/client/pages/dynamic-page/content/MobilePageContentContainer.tsx +++ b/packages/plugins/@nocobase/plugin-mobile/src/client/pages/dynamic-page/content/MobilePageContentContainer.tsx @@ -7,12 +7,16 @@ * For more information, please refer to: https://www.nocobase.com/agreement. */ +import { useToken } from '@nocobase/client'; import _ from 'lodash'; import React, { FC, useEffect } from 'react'; +import { PageBackgroundColor } from '../../../constants'; export const MobilePageContentContainer: FC<{ hideTabBar?: boolean }> = ({ children, hideTabBar }) => { const [mobileTabBarHeight, setMobileTabBarHeight] = React.useState(0); const [mobilePageHeader, setMobilePageHeader] = React.useState(0); + const { token } = useToken(); + useEffect(() => { const navigationBar = _.last(document.querySelectorAll('.mobile-page-header')); setMobilePageHeader(navigationBar?.offsetHeight); @@ -34,6 +38,9 @@ export const MobilePageContentContainer: FC<{ hideTabBar?: boolean }> = ({ child boxSizing: 'border-box', maxWidth: '100%', overflowX: 'hidden', + backgroundColor: PageBackgroundColor, + paddingInline: token.paddingPageHorizontal, + paddingBlock: token.paddingPageVertical, }} > {children}