From 976f556e61b950ad63a3d44bd820ad1bf70febc1 Mon Sep 17 00:00:00 2001 From: rdmclin2 Date: Thu, 24 Aug 2023 19:45:51 +0800 Subject: [PATCH] :bug: feat: auto generate id --- src/ColumnList/ColumnList.tsx | 37 ++++++++++++++++++++--- src/SortableList/container/index.tsx | 6 ++-- src/SortableList/demos/_ItemRender.tsx | 3 +- src/SortableList/demos/controlled.tsx | 3 +- src/SortableList/demos/data.ts | 11 ++++--- src/SortableList/hooks/useSortableList.ts | 16 +++++----- src/SortableList/index.ts | 10 ++++-- src/SortableList/store/listDataReducer.ts | 1 - src/SortableList/store/store.ts | 3 +- src/SortableList/type/action.ts | 2 +- src/SortableList/type/component.ts | 2 +- src/SortableList/type/store.ts | 11 ++++--- 12 files changed, 73 insertions(+), 32 deletions(-) diff --git a/src/ColumnList/ColumnList.tsx b/src/ColumnList/ColumnList.tsx index c5dffbe7..d13c182b 100644 --- a/src/ColumnList/ColumnList.tsx +++ b/src/ColumnList/ColumnList.tsx @@ -1,6 +1,6 @@ import { getPrefixCls, SortableList } from '@ant-design/pro-editor'; import { cx } from 'antd-style'; -import { forwardRef, ReactNode, useCallback } from 'react'; +import { forwardRef, ReactNode, useCallback, useMemo } from 'react'; import { SortableListProps, SortableListRef } from '../SortableList'; import ColumnItem from './ColumnItem'; @@ -11,16 +11,43 @@ export interface ColumnListProps extends SortableListProps { columns: ColumnItemList; } +const genUniqueID = (_, index) => { + return `columnlist_${index}_${Math.floor(Math.random() * 10000)}_${Date.now()}`; +}; + const ColumnList: (props: ColumnListProps) => ReactNode = forwardRef< - SortableListRef, + SortableListRef, ColumnListProps ->(({ prefixCls: customPrefixCls, className, columns, ...props }, ref) => { +>(({ prefixCls: customPrefixCls, className, columns, value, initialValues, ...props }, ref) => { const prefixCls = getPrefixCls('column-list', customPrefixCls); + // 校验是否传入 ID,如果没有传入 ID,就生成一个 ID + const parsedValue = useMemo( + () => + value + ? value.map((item, index) => ({ + id: genUniqueID(item, index), + ...item, + })) + : undefined, + [value], + ); + // 校验是否传入 ID,如果没有传入 ID,就生成一个 ID + const parsedInitialValues = useMemo( + () => + initialValues + ? initialValues.map((item, index) => ({ + id: genUniqueID(item, index), + ...item, + })) + : undefined, + [initialValues], + ); const renderHeader = useCallback( () =>
, [columns], ); + const renderContent = useCallback( (item, index) => ( @@ -29,11 +56,13 @@ const ColumnList: (props: ColumnListProps) => ReactNode = forwardRef ); return ( - + diff --git a/src/SortableList/container/index.tsx b/src/SortableList/container/index.tsx index 22566345..0d6f2b43 100644 --- a/src/SortableList/container/index.tsx +++ b/src/SortableList/container/index.tsx @@ -1,6 +1,6 @@ import { forwardRef, memo, ReactNode } from 'react'; import { ConfigProvider } from '../../ConfigProvider'; -import type { StoreUpdaterProps } from '../type'; +import type { SortableItem, StoreUpdaterProps } from '../type'; import type { AppProps } from './App'; import App from './App'; import { SortableListProvider } from './Provider'; @@ -10,7 +10,9 @@ export { SortableListProvider } from './Provider'; export interface SortableListProps extends StoreUpdaterProps, AppProps {} -export const SortableList: (props: SortableListProps) => ReactNode = memo( +export const SortableList: ( + props: SortableListProps, +) => ReactNode = memo( forwardRef((props, ref) => { const { SHOW_STORE_IN_DEVTOOLS, className, style, ...res } = props; return ( diff --git a/src/SortableList/demos/_ItemRender.tsx b/src/SortableList/demos/_ItemRender.tsx index 3fa14154..5b6b7f32 100644 --- a/src/SortableList/demos/_ItemRender.tsx +++ b/src/SortableList/demos/_ItemRender.tsx @@ -20,7 +20,8 @@ const ItemRender = ({ item, index, compact = false }: ItemRenderProps) => { const value = instance.getValue() || []; // 如果是最后一个节点,按下回车后,会自动添加一个新的节点 if (index + 1 === value.length) { - instance.addItem({ title: `new-${randomIndex()}` }); + const id = randomIndex(); + instance.addItem({ id, title: `new-${randomIndex()}` }); } else { const nextNodeEl = document.getElementById(`index-${index + 1}`); nextNodeEl?.focus(); diff --git a/src/SortableList/demos/controlled.tsx b/src/SortableList/demos/controlled.tsx index df3718af..eb189b73 100644 --- a/src/SortableList/demos/controlled.tsx +++ b/src/SortableList/demos/controlled.tsx @@ -3,13 +3,14 @@ * description: onChange 会返回变更数据 * compact: true */ +import type { SortableItemList } from '@ant-design/pro-editor'; import { SortableList } from '@ant-design/pro-editor'; import { useTheme } from 'antd-style'; import { useState } from 'react'; import { Flexbox } from 'react-layout-kit'; const Demo = () => { - const [list, setList] = useState([{ id: 'hello' }, { id: 'world' }]); + const [list, setList] = useState([{ id: 'hello' }, { id: 'world' }]); const token = useTheme(); return ( diff --git a/src/SortableList/demos/data.ts b/src/SortableList/demos/data.ts index 67cbdc6f..a086a566 100644 --- a/src/SortableList/demos/data.ts +++ b/src/SortableList/demos/data.ts @@ -1,7 +1,9 @@ -export type SchemaItem = { +import { SortableItem } from '@ant-design/pro-editor'; + +export type SchemaItem = SortableItem<{ title?: string; dataIndex?: string; -}; +}>; export interface ItemRenderProps { item: SchemaItem; @@ -19,12 +21,13 @@ export const fieldStyle: React.CSSProperties = { }; export const INIT_VALUES = [ - { title: '序号', dataIndex: 'indexBorder' }, + { id: 'index', title: '序号', dataIndex: 'indexBorder' }, { + id: 'authName', title: '授权企业名称', dataIndex: 'text', }, - { title: '被授权企业', dataIndex: 'select' }, + { id: 'authedName', title: '被授权企业', dataIndex: 'select' }, ]; /* diff --git a/src/SortableList/hooks/useSortableList.ts b/src/SortableList/hooks/useSortableList.ts index 7ebb4f13..ceebc0ee 100644 --- a/src/SortableList/hooks/useSortableList.ts +++ b/src/SortableList/hooks/useSortableList.ts @@ -1,11 +1,11 @@ import { useMemoizedFn } from 'ahooks'; import { useStoreApi } from '../store'; -import { UniqueIdentifier } from '../type/type'; +import { SortableItem, UniqueIdentifier } from '../type'; /** * SortableList 实例对象 * @template T 节点数据类型 */ -export interface SortableListInstance { +export interface SortableListInstance { /** * 获取当前激活节点的 id * @returns 当前激活节点的 id @@ -15,14 +15,14 @@ export interface SortableListInstance { * 获取当前树的数据 * @returns 当前树的数据 */ - getValue: () => T[]; + getValue: () => SortableItem[]; /** * 添加项 * @param item 数据 * @param index 列表索引 * @returns */ - addItem: (item?: T, index?: number) => void; + addItem: (item?: SortableItem, index?: number) => void; /** * 删除项 * @param index 列表索引 @@ -35,19 +35,19 @@ export interface SortableListInstance { * @param index 列表索引 * @returns */ - updateItem: (item: T, index: number) => void; + updateItem: (item: Partial, index: number) => void; } -export const useSortableList = (): SortableListInstance => { +export const useSortableList = (): SortableListInstance => { const storeApi = useStoreApi(); const getActiveId = useMemoizedFn(() => storeApi.getState().activeId); const getValue = useMemoizedFn(() => storeApi.getState().value); - const addItem = (item?: T, index?: number) => + const addItem = (item?: SortableItem, index?: number) => storeApi.getState().dispatchListData({ type: 'addItem', item, index }); const removeItem = (index: number) => storeApi.getState().dispatchListData({ type: 'removeItem', index }); - const updateItem = (item: T, index: number) => + const updateItem = (item: Partial, index: number) => storeApi.getState().dispatchListData({ type: 'updateItem', item, index }); return { diff --git a/src/SortableList/index.ts b/src/SortableList/index.ts index 8ab874c7..778089d1 100644 --- a/src/SortableList/index.ts +++ b/src/SortableList/index.ts @@ -1,8 +1,12 @@ export * from './container'; // hooks 和相关类型定义 -export type { SortableListRef } from './container/StoreUpdater'; export { useSortableList } from './hooks/useSortableList'; export type { SortableListInstance } from './hooks/useSortableList'; -export type { SortableListDispatchPayload } from './store'; -export type { CreatorButtonProps } from './type/type'; +export type { + CreatorButtonProps, + SortableItem, + SortableItemList, + SortableListDispatchPayload, + SortableListRef, +} from './type'; diff --git a/src/SortableList/store/listDataReducer.ts b/src/SortableList/store/listDataReducer.ts index 57a369ea..ec1a6270 100644 --- a/src/SortableList/store/listDataReducer.ts +++ b/src/SortableList/store/listDataReducer.ts @@ -12,7 +12,6 @@ export const listDataReducer = (value: any[], payload: SortableListDispatchPaylo const overIndex = getIndexOfActiveItem(value, targetId); if (activeIndex === overIndex) return; - // Do not handle out of range if ( activeIndex < 0 || activeIndex >= value.length || diff --git a/src/SortableList/store/store.ts b/src/SortableList/store/store.ts index 449dbd63..c0efdb5c 100644 --- a/src/SortableList/store/store.ts +++ b/src/SortableList/store/store.ts @@ -2,6 +2,7 @@ import type { DragEndEvent, DragStartEvent } from '@dnd-kit/core'; import isEqual from 'lodash.isequal'; import type { StateCreator } from 'zustand/vanilla'; import type { SortableListState } from '../type'; +import { SortableListDispatchPayload } from '../type'; import { initialState } from './initialState'; import { listDataReducer } from './listDataReducer'; @@ -10,7 +11,7 @@ interface Action { handleDragStart: (event: DragStartEvent) => void; handleDragEnd: (event: DragEndEvent) => void; handleDragCancel: () => void; - dispatchListData: (payload: any) => void; + dispatchListData: (payload: SortableListDispatchPayload) => void; } export type Store = SortableListState & Action; diff --git a/src/SortableList/type/action.ts b/src/SortableList/type/action.ts index 2a32a4d7..188321f3 100644 --- a/src/SortableList/type/action.ts +++ b/src/SortableList/type/action.ts @@ -59,7 +59,7 @@ export interface UpdateItemAction { /** * 修改后的节点内容 */ - item: SortableItem; + item: Partial; } /** diff --git a/src/SortableList/type/component.ts b/src/SortableList/type/component.ts index 160b4ca8..c91c56ab 100644 --- a/src/SortableList/type/component.ts +++ b/src/SortableList/type/component.ts @@ -63,7 +63,7 @@ export interface CreatorButtonProps { /** * 生成初始值逻辑 */ - record?: (index: number) => Record; + record?: (index: number) => SortableItem; /** * 新增一行按钮文案 */ diff --git a/src/SortableList/type/store.ts b/src/SortableList/type/store.ts index 6d8cc6b2..3501512a 100644 --- a/src/SortableList/type/store.ts +++ b/src/SortableList/type/store.ts @@ -4,6 +4,7 @@ import type { GetItemStyles, RenderActionProps, RenderItemProps, + SortableItem, SortableItemList, SortableListDispatchPayload, UniqueIdentifier, @@ -61,13 +62,13 @@ export interface SortableListState { /** * 供外部使用的 ref 方法 */ -export interface SortableListRef { - addItem: (item?: T, index?: number) => void; +export interface SortableListRef { + addItem: (item?: SortableItem, index?: number) => void; removeItem: (index: number) => void; - updateItem: (item: T, index: number) => void; + updateItem: (item: SortableItem, index: number) => void; } -export interface StoreUpdaterProps { +export interface StoreUpdaterProps { /** * 值 */ @@ -95,7 +96,7 @@ export interface StoreUpdaterProps { /** * 对外部暴露方法 */ - ref?: ForwardedRef>; + ref?: ForwardedRef; /** * 新建对象相关属性 */