diff --git a/package.json b/package.json index c0e2852..3bac782 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,11 @@ "preview": "vite preview" }, "dependencies": { + "@ant-design/cssinjs": "^1.21.1", "@ant-design/icons": "^5.3.6", "@ant-design/pro-components": "^2.7.0", + "@ant-design/pro-layout": "^7.19.12", + "@ant-design/pro-provider": "^2.14.9", "@formily/antd-v5": "^1.2.0", "@formily/core": "^2.3.1", "@formily/react": "^2.3.1", @@ -34,6 +37,7 @@ "jotai-devtools": "^0.9.1", "jotai-scope": "^0.5.1", "jotai-tanstack-query": "^0.8.5", + "lodash": "^4.17.21", "re-resizable": "^6.9.11", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -43,6 +47,7 @@ "react-rnd": "^10.4.2-test2", "react-use": "^17.5.0", "throttle-debounce": "^5.0.0", + "use-merge-value": "^1.2.0", "wonka": "^6.3.4" }, "devDependencies": { diff --git a/src/components/draggable-panel/FloatMode.tsx b/src/components/draggable-panel/FloatMode.tsx index b163255..1541665 100644 --- a/src/components/draggable-panel/FloatMode.tsx +++ b/src/components/draggable-panel/FloatMode.tsx @@ -8,84 +8,84 @@ import { Rnd } from 'react-rnd' import { useStyle } from './style' export interface FloatProps { - /** - * 位置, - * 使用固定模式或者浮动窗口 - */ - mode?: 'fixed' | 'float'; + /** + * 位置, + * 使用固定模式或者浮动窗口 + */ + mode?: 'fixed' | 'float'; - /** - * 面板的朝向,默认是 左右模式 - * @default horizontal - */ - direction?: 'vertical' | 'horizontal'; + /** + * 面板的朝向,默认是 左右模式 + * @default horizontal + */ + direction?: 'vertical' | 'horizontal'; - /** - * 最小宽度 - */ - minWidth?: number; - /** - * 最小高度 - */ - minHeight?: number; - /** - * 最大宽度 - */ - maxWidth?: number; - /** - * 最大高度 - */ - maxHeight?: number; - /** - * 控制可缩放区域 - */ - resize?: RndProps['enableResizing']; - /** - * 面板尺寸 - * - */ - size?: Partial; - onSizeChange?: (delta: NumberSize, size?: Size) => void; - /** - * 当用户在拖拽过程中触发 - * @param delta - * @param size - */ - onSizeDragging?: (delta: NumberSize, size?: Size) => void; + /** + * 最小宽度 + */ + minWidth?: number; + /** + * 最小高度 + */ + minHeight?: number; + /** + * 最大宽度 + */ + maxWidth?: number; + /** + * 最大高度 + */ + maxHeight?: number; + /** + * 控制可缩放区域 + */ + resize?: RndProps['enableResizing']; + /** + * 面板尺寸 + * + */ + size?: Partial; + onSizeChange?: (delta: NumberSize, size?: Size) => void; + /** + * 当用户在拖拽过程中触发 + * @param delta + * @param size + */ + onSizeDragging?: (delta: NumberSize, size?: Size) => void; - canResizing?: boolean; - /** - * 面板位置 - * 受控模式 - */ - position?: RndProps['position']; - /** - * 面板默认尺寸 - * 固定模式下: width 320px height 100% - * 浮动模式下:width 320px height 400px - */ - defaultSize?: Partial; - /** - * 面板默认位置悬浮模式下有效 - * @default [100,100] - */ - defaultPosition?: RndProps['position']; - /** - * 位置变更回调 - */ - onPositionChange?: (position: RndProps['position']) => void; - /** - * 样式 - */ - style?: CSSProperties; - /** - * 类名 - */ - className?: string; - /** - * 内容 - */ - children: ReactNode; + canResizing?: boolean; + /** + * 面板位置 + * 受控模式 + */ + position?: RndProps['position']; + /** + * 面板默认尺寸 + * 固定模式下: width 320px height 100% + * 浮动模式下:width 320px height 400px + */ + defaultSize?: Partial; + /** + * 面板默认位置悬浮模式下有效 + * @default [100,100] + */ + defaultPosition?: RndProps['position']; + /** + * 位置变更回调 + */ + onPositionChange?: (position: RndProps['position']) => void; + /** + * 样式 + */ + style?: CSSProperties; + /** + * 类名 + */ + className?: string; + /** + * 内容 + */ + children: ReactNode; } const DEFAULT_HEIGHT = 300 @@ -93,90 +93,90 @@ const DEFAULT_WIDTH = 400 export const FloatMode: FC = memo( ({ - children, - direction, - resize, - style, - position, - onPositionChange, - size, - defaultSize: customizeDefaultSize, - defaultPosition: customizeDefaultPosition, - minWidth = 280, - minHeight = 200, - maxHeight, - maxWidth, - canResizing, + children, + direction, + resize, + style, + position, + onPositionChange, + size, + defaultSize: customizeDefaultSize, + defaultPosition: customizeDefaultPosition, + minWidth = 280, + minHeight = 200, + maxHeight, + maxWidth, + canResizing, }) => { - const { styles } = useStyle() + const { styles } = useStyle() - const resizeHandleClassNames: HandleClassName = useMemo(() => { - if (!canResizing) return {} + const resizeHandleClassNames: HandleClassName = useMemo(() => { + if (!canResizing) return {} - return { - right: styles.rightHandle, - left: styles.leftHandle, - top: styles.topHandle, - bottom: styles.bottomHandle, - } - }, [ canResizing, direction ]) - - const resizing = useMemo(() => { - if (canResizing) return resize + return { + right: styles.rightHandle, + left: styles.leftHandle, + top: styles.topHandle, + bottom: styles.bottomHandle, + } + }, [ canResizing, direction ]) - return { - top: true, - bottom: true, - right: true, - left: true, - topRight: true, - bottomRight: true, - bottomLeft: true, - topLeft: true, - ...(resize as Enable), - } - }, [ canResizing, resize ]) + const resizing = useMemo(() => { + if (canResizing) return resize - const defaultSize: Size = { - width: DEFAULT_WIDTH, - height: DEFAULT_HEIGHT, - ...customizeDefaultSize, + return { + top: true, + bottom: true, + right: true, + left: true, + topRight: true, + bottomRight: true, + bottomLeft: true, + topLeft: true, + ...(resize as Enable), } + }, [ canResizing, resize ]) - const defaultPosition: Position = { - x: 100, - y: 100, - ...customizeDefaultPosition, - } + const defaultSize: Size = { + width: DEFAULT_WIDTH, + height: DEFAULT_HEIGHT, + ...customizeDefaultSize, + } - const sizeProps = { - minWidth: Math.max(minWidth, 0), - minHeight: Math.max(minHeight, 0), - maxHeight: maxHeight ? Math.max(maxHeight, 0) : undefined, - maxWidth: maxWidth ? Math.max(maxWidth, 0) : undefined, - defaultSize, - size: size as Size, - style, - } + const defaultPosition: Position = { + x: 100, + y: 100, + ...customizeDefaultPosition, + } + + const sizeProps = { + minWidth: Math.max(minWidth, 0), + minHeight: Math.max(minHeight, 0), + maxHeight: maxHeight ? Math.max(maxHeight, 0) : undefined, + maxWidth: maxWidth ? Math.max(maxWidth, 0) : undefined, + defaultSize, + size: size as Size, + style, + } - return ( - { - onPositionChange?.({ x: data.x, y: data.y }) - }} - bound={'parent'} - enableResizing={resizing} - {...sizeProps} - className={styles.float} - > - {children} - - ) + return ( + { + onPositionChange?.({ x: data.x, y: data.y }) + }} + bound={'parent'} + enableResizing={resizing} + {...sizeProps as any} + className={styles.float} + > + {children} + + ) }, ) \ No newline at end of file diff --git a/src/components/r-form/index.tsx b/src/components/r-form/index.tsx index 114e944..c47f638 100644 --- a/src/components/r-form/index.tsx +++ b/src/components/r-form/index.tsx @@ -301,7 +301,7 @@ const RForm = ({ namespace, columns: propColumns = [], title }: RFormProps) => { }} - onFinish={async (values) => { + onFinish={async (values: any) => { //处理,变成数组 Object.keys(values).forEach(key => { if (typeof values[key] === 'string' && values[key].includes(',')) { diff --git a/src/components/r-form/utils/index.tsx b/src/components/r-form/utils/index.tsx index 971be25..d96665b 100644 --- a/src/components/r-form/utils/index.tsx +++ b/src/components/r-form/utils/index.tsx @@ -49,7 +49,7 @@ export const transformAntdTableProColumns = (columns: ProColumns[], overwriteCol const type = getValueType(item) - const overwrite = overwriteColumns?.find(i => i.dataIndex === item.dataIndex || item.name) + const overwrite = overwriteColumns?.find(i => i.dataIndex === item.dataIndex) if (overwrite) { overwriteKeys.push(item.dataIndex) } diff --git a/src/pages/x-form/hooks/useApi.tsx b/src/pages/x-form/hooks/useApi.tsx deleted file mode 100644 index 1e6e396..0000000 --- a/src/pages/x-form/hooks/useApi.tsx +++ /dev/null @@ -1,111 +0,0 @@ -import { useNavigate, useRouterState } from '@tanstack/react-router' -import { useAtom } from 'jotai/index' -import { apiAtom } from '@/store/x-form/model.ts' -import { useCallback, useEffect, useRef, useState } from 'react' -import { Input, message, Modal } from 'antd' -import { Route } from '@/pages/x-form' -import { useApiContext } from '@/context.ts' - -export const useApi = () => { - - const { location } = useRouterState() - const apiCtx = useApiContext() - const nav = useNavigate() - const [ api, setApi ] = useAtom(apiAtom) - const { api: apiParam } = Route.useSearch() - const [ isChange, setChange ] = useState(false) - const [ innerApi, setInnerApi ] = useState('') - const [ open, setOpen ] = useState(false) - const apiRef = useRef(apiParam) - - - useEffect(() => { - - if (apiCtx.isApi && apiCtx.api) { - apiRef.current = apiCtx.api - setApi(apiCtx.api) - return - } - - if (!apiParam && api) { - apiRef.current = api - nav({ - to: location.pathname, - search: { - api - } - }) - return - } - - if (apiParam && !api) { - apiRef.current = apiParam - setApi(apiParam) - return - } - - //延时弹出 - setTimeout(() => { - if (!apiRef.current) { - setOpen(true) - } - }, 2000) - - }, [ api, apiParam, apiCtx ]) - - const onOK = useCallback(() => { - if (!innerApi) { - message.destroy() - message.error('请填写 api 参数') - return - } - setChange(false) - setOpen(false) - setApi(innerApi) - setChange(true) - - nav({ - to: location.pathname, - search: { - api: innerApi - } - }) - }, [ innerApi ]) - - const holderElement = ( - <> - { - setOpen(false) - }} - onOk={() => { - onOK() - }} - > - { - if (e.key === 'Enter') { - onOK() - } - }} - onChange={e => { - setInnerApi(e.target.value) - }}/> - - - ) - return { - holderElement, - updateApi: setOpen, - setApi, - apiChange: isChange, - api, - apiCtx, - } as const - -} \ No newline at end of file diff --git a/src/pages/x-form/utils/index.tsx b/src/pages/x-form/utils/index.tsx deleted file mode 100644 index f16e53e..0000000 --- a/src/pages/x-form/utils/index.tsx +++ /dev/null @@ -1,146 +0,0 @@ -import { XFormTypes } from '@/types/x-form/model' -import { ProColumns } from '@ant-design/pro-components' -import Switch from '@/components/switch' -import { Checkbox, DatePicker, Input, Radio, Select, TreeSelect } from 'antd' -import request from '@/request' -import { convertToBool, genProTableColumnWidthProps } from '@/utils' -import { ReactNode } from 'react' - -const getValueType = (column: XFormTypes.IColumn) => { - switch (column.type) { - case 'input': - return 'text' - case 'select': - return 'select' - case 'date': - return 'date' - case 'switch': - return 'switch' - case 'radio': - return 'radio' - case 'checkbox': - return 'checkbox' - case 'textarea': - return 'textarea' - case 'tree': - return 'treeSelect' - default: - return 'text' - } -} - -//根据type返回对应的组件 -const getComponent = (column: XFormTypes.IColumn) => { - const type = getValueType(column) as any - switch (type) { - case 'input': - return Input - case 'select': - return Select - case 'date': - return DatePicker - case 'switch': - return Switch - case 'radio': - return Radio - case 'checkbox': - return Checkbox - case 'textarea': - return Input.TextArea - case 'tree': - case 'treeSelect': - return TreeSelect - default: - return Input - } -} - - -export const transformAntdTableProColumns = (columns: XFormTypes.IColumn[]) => { - - return (columns || []).map(item => { - const { value, props, multiple, checkStrictly } = item - - const { width, fieldProps: _fieldProps } = genProTableColumnWidthProps(item.width) - const fieldProps: ProColumns['fieldProps'] = { - dataFiledNames: props, - ...(multiple ? { multiple: true } : {}), - ...(checkStrictly ? { treeCheckStrictly: true } : {}), - ..._fieldProps, - } - - const formItemProps: ProColumns['formItemProps'] = (form, config) => { - - return { - rules: item.rules?.map(i => { - return { - required: i.required, - message: i.message - } - }), - ...(value ? { valuePropName: value } : {}) - } - } - - const rowProps = item.gutter ? { gutter: item.gutter } : { gutter: [ 16, 0 ], } - const colProps = item.span ? { span: item.span } : {} - - const type = getValueType(item) - return { - title: item.label, - dataIndex: item.prop, - key: item.prop, - width, - valueType: type, - hideInSearch: !item.search, - hideInTable: item.hide, - fieldProps, - formItemProps, - colProps, - rowProps, - request: item.dicUrl ? async (params, props) => { - const { fieldProps: { dataFiledNames } } = props - const { value, res: resKey, label } = dataFiledNames || {} - const url = `/${item.dicUrl.replace(/^:/, '/')}` - return request[item.dicMethod || 'get'](url, params).then(res => { - return (res.data?.[resKey] || res.data || []).map((i: any) => { - // console.log(i) - const disabled = 'disabled' in i ? i.disabled : - ('status' in i ? !convertToBool(i.status) : false) - return { - title: i[label || 'label'], - label: i[label || 'label'], - value: i[value || 'id'], - disabled, - data: i - } - }) - }) - } : undefined, - renderFormItem: (_scheam, config) => { - const Component = getComponent(item) as any - const { options, ...props } = config as any - - if ([ 'tree', 'treeSelect' ].includes(_scheam.valueType as string)) { - return - } - if (_scheam.valueType as string === 'select') { - return