diff --git a/docs/drip-table-generator/preview/sample.module.less b/docs/drip-table-generator/preview/sample.module.less index 5afdf25..3d1f4c4 100644 --- a/docs/drip-table-generator/preview/sample.module.less +++ b/docs/drip-table-generator/preview/sample.module.less @@ -1,3 +1,4 @@ +/* stylelint-disable selector-class-pattern */ .__dumi-default-layout[data-route="/drip-table-generator/preview"] { padding-top: 64px; padding-left: 0; @@ -12,5 +13,9 @@ padding: 16px 16px; border-bottom: 1px solid #e6e6ee; box-shadow: 0 1px 4px -1px rgba(0, 0, 0, .05); + + .header-button { + margin: 0 12px; + } } } diff --git a/docs/drip-table-generator/preview/sample.tsx b/docs/drip-table-generator/preview/sample.tsx index 9251527..bdcad56 100755 --- a/docs/drip-table-generator/preview/sample.tsx +++ b/docs/drip-table-generator/preview/sample.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { Button, Row } from 'antd'; import { DripTableSchema } from 'drip-table'; import DripTableDriverAntDesign from 'drip-table-driver-antd'; -import DripTableGenerator from 'drip-table-generator'; +import DripTableGenerator, { DripTableGeneratorHandler } from 'drip-table-generator'; import 'antd/dist/antd.css'; import 'drip-table-generator/index.css'; @@ -53,9 +53,7 @@ const initialSchema: DripTableSchema = { const Demo = (props: { showHeader: boolean }) => { - const generator: React.MutableRefObject void; - }> = React.useRef(null); + const generator: React.MutableRefObject = React.useRef(null); const views = { demoHeader: props.showHeader !== false, @@ -65,17 +63,18 @@ const Demo = (props: { showHeader: boolean }) => { { views.demoHeader && ( - + + )} { console.log(schema); }} + onExportSchema={schema => { console.log(schema); }} customComponents={{ custom: { TextComponent } }} customComponentPanel={components} /> diff --git a/packages/drip-table-generator/src/context.ts b/packages/drip-table-generator/src/context.ts index 34b579e..d1614db 100755 --- a/packages/drip-table-generator/src/context.ts +++ b/packages/drip-table-generator/src/context.ts @@ -1,7 +1,4 @@ import { createContext } from 'react'; -import { DripTableRecordTypeBase } from 'drip-table'; import { DripTableGeneratorProps } from '@/typing'; -export type IDripTableGeneratorContext = DripTableGeneratorProps; - -export const Ctx = createContext>>({}); +export const Ctx = createContext({}); diff --git a/packages/drip-table-generator/src/drip-table-generator.tsx b/packages/drip-table-generator/src/drip-table-generator.tsx index 06d132c..cefe074 100644 --- a/packages/drip-table-generator/src/drip-table-generator.tsx +++ b/packages/drip-table-generator/src/drip-table-generator.tsx @@ -1,17 +1,19 @@ import React, { useState, forwardRef, useImperativeHandle, useRef } from 'react'; import { ConfigProvider } from 'antd'; -import { ColumnConfig, DripTableRecordTypeBase, DripTableSchema } from 'drip-table'; +import { ColumnConfig, DripTableSchema } from 'drip-table'; import zhCN from 'antd/lib/locale/zh_CN'; import { Ctx } from '@/context'; import { DripTableGeneratorProps, DripTableGeneratorHandler } from '@/typing'; -import { defaultState, GlobalStore } from '@/store'; +import { defaultState, DripTableGeneratorState, GlobalStore } from '@/store'; -import Wrapper from './wrapper'; +import Wrapper, { GeneratorWrapperHandler } from './wrapper'; -import 'antd/dist/antd.less'; - -const useTableRoot = (props, store, wrapper) => { +const useTableRoot = ( + props: DripTableGeneratorProps, + store: [DripTableGeneratorState, React.Dispatch>], + wrapper: React.MutableRefObject, +) => { const [state, setState] = store; const getSchemaValue = (): DripTableSchema => { @@ -36,24 +38,34 @@ const useTableRoot = (props, store, wrapper) => { }; }; + const getDataSource = () => { + if (wrapper.current) { + const currentState = wrapper.current.getState(); + return currentState.previewDataSource; + } + return state.previewDataSource; + }; + const context = { ...props, + ...state, getSchemaValue, + getDataSource, setGlobalData: setState, }; return context; }; -const Container = (props: DripTableGeneratorProps, ref: React.ForwardedRef) => { - const wrapper = useRef({}); +const Container = (props: DripTableGeneratorProps, ref: React.ForwardedRef) => { + const wrapper = useRef(null); const initialState = defaultState(); const store = useState(initialState); const context = useTableRoot(props, store, wrapper); useImperativeHandle(ref, () => context); - const WrapperRef = forwardRef & { store: GlobalStore }>(Wrapper); + const WrapperRef = forwardRef(Wrapper); return ( diff --git a/packages/drip-table-generator/src/layout/attribute-layout/index.tsx b/packages/drip-table-generator/src/layout/attribute-layout/index.tsx index 6873581..ae88c14 100644 --- a/packages/drip-table-generator/src/layout/attribute-layout/index.tsx +++ b/packages/drip-table-generator/src/layout/attribute-layout/index.tsx @@ -7,7 +7,7 @@ */ import React from 'react'; -import { Result, Tabs } from 'antd'; +import { Alert, Result, Tabs } from 'antd'; import { ExclamationCircleTwoTone } from '@ant-design/icons'; import { DripTableSchema } from 'drip-table'; import MonacoEditor from '@monaco-editor/react'; @@ -38,12 +38,14 @@ const { TabPane } = Tabs; const AttributeLayout = (props: Props & { store: GlobalStore }) => { const { dataFields } = useGlobalData(); + const [state, setState] = props.store; + const store = { state, setState }; + const [activeKey, setActiveKey] = React.useState('0'); - const [state, actions] = props.store; - const store = { state, setState: actions }; + const [codeErrorMessage, setCodeErrorMessage] = React.useState(''); - const [code, setCode] = React.useState(JSON.stringify(state.dataSource, null, 4)); + const code = JSON.stringify(state.previewDataSource, null, 4); const getActiveKey = () => { if (activeKey === '0') { @@ -129,17 +131,22 @@ const AttributeLayout = (props: Props & { store: GlobalStore }) => { } as DripTableColumn; }; - /** TODO: 报错逻辑后续优化 */ - function submitDataWithoutThrottle() { + /** TODO: 报错逻辑后续优化 + * + * @param {string} codeValue JSON + */ + const submitDataWithoutDebounce = (codeValue: string) => { + setCodeErrorMessage(''); try { - state.dataSource = JSON.parse(code); - globalActions.updateDataSource(store); + state.previewDataSource = JSON.parse(codeValue); + setState({ ...state }); + globalActions.updatePreviewDataSource(store); } catch (error) { - console.error(error); + setCodeErrorMessage((error as Error).message); } - } + }; - const submitTableData = debounce(submitDataWithoutThrottle, 1000); + const submitTableData = debounce(submitDataWithoutDebounce, 1000); const renderGlobalForm = () => ( @@ -169,7 +176,7 @@ const AttributeLayout = (props: Props & { store: GlobalStore }) => { return; } if (uiProps.from === 'dataSource') { - uiProps.options = Object.keys(state.dataSource[0] || {}) + uiProps.options = Object.keys(state.previewDataSource[0] || {}) .map(key => ({ label: key, value: key })); } else if (uiProps.from === 'dataFields') { uiProps.options = dataFields?.map(key => ({ label: key, value: key })) || []; @@ -181,7 +188,7 @@ const AttributeLayout = (props: Props & { store: GlobalStore }) => { return; } if (itemUiProps.from === 'dataSource') { - itemUiProps.options = Object.keys(state.dataSource[0] || {}) + itemUiProps.options = Object.keys(state.previewDataSource[0] || {}) .map(key => ({ label: key, value: key })); } else if (itemUiProps.from === 'dataFields') { itemUiProps.options = dataFields?.map(key => ({ label: key, value: key })) || []; @@ -226,13 +233,14 @@ const AttributeLayout = (props: Props & { store: GlobalStore }) => {
+ { codeErrorMessage && } { setCode(value || ''); submitTableData(); }} + onChange={(value) => { submitTableData(value); }} />
diff --git a/packages/drip-table-generator/src/layout/editable-table/index.tsx b/packages/drip-table-generator/src/layout/editable-table/index.tsx index bf3e5b3..7630d03 100644 --- a/packages/drip-table-generator/src/layout/editable-table/index.tsx +++ b/packages/drip-table-generator/src/layout/editable-table/index.tsx @@ -18,12 +18,12 @@ import Draggable from '@/components/Draggable'; import styles from './index.module.less'; import { get } from '@/utils'; -interface Props { - driver: DripTableDriver; - customComponents: DripTableProps['components'] | undefined; +interface Props { + driver: DripTableDriver; + customComponents: DripTableProps['components'] | undefined; } -const EditableTable = (props: Props & { store: GlobalStore }) => { +const EditableTable = (props: Props & { store: GlobalStore }) => { const [state, actions] = props.store; const store = { state, setState: actions }; @@ -36,8 +36,8 @@ const EditableTable = (props: Props< const DripTableComponent = column['ui:type'].startsWith('custom::') ? customComponents[column['ui:type'].replace('custom::', '')] : builtInComponents[column['ui:type']]; - const hasRecord = !(!state.dataSource || state.dataSource.length <= 0); - const record = state.dataSource[0] || {} as Record; + const hasRecord = !(!state.previewDataSource || state.previewDataSource.length <= 0); + const record = state.previewDataSource[0] || {} as Record; const value = column.dataIndex ? get(record, column.dataIndex) : record; const errorBoundary = () => { @@ -92,23 +92,23 @@ const EditableTable = (props: Props<
{ col.title }
{ previewComponentRender(col) } { isCurrent && ( - { - const index = state.columns.findIndex(item => item.$id === state.currentColumn?.$id); - if (index > -1) { - state.columns.splice(index, 1); - for (let i = index; i < state.columns.length; i++) { - state.columns[i].key = i + 1; - state.columns[i].sort = i + 1; - } - state.currentColumn = void 0; - globalActions.editColumns(store); - globalActions.checkColumn(store); + { + const index = state.columns.findIndex(item => item.$id === state.currentColumn?.$id); + if (index > -1) { + state.columns.splice(index, 1); + for (let i = index; i < state.columns.length; i++) { + state.columns[i].key = i + 1; + state.columns[i].sort = i + 1; } - }} - /> + state.currentColumn = void 0; + globalActions.editColumns(store); + globalActions.checkColumn(store); + } + }} + /> ) } ); @@ -117,21 +117,21 @@ const EditableTable = (props: Props< return (
{ - state.columns && state.columns.length > 0 - ? ( - - value={(state.columns || []) as DripTableColumn[]} - codeKey="sort" - style={{ position: 'relative' }} - onChange={(data) => { - state.columns = [...data]; - globalActions.editColumns(store); - }} - render={renderTableCell} - /> - ) - : - } + state.columns && state.columns.length > 0 + ? ( + + value={(state.columns || []) as DripTableColumn[]} + codeKey="sort" + style={{ position: 'relative' }} + onChange={(data) => { + state.columns = [...data]; + globalActions.editColumns(store); + }} + render={renderTableCell} + /> + ) + : + }
); }; diff --git a/packages/drip-table-generator/src/layout/preview-table/index.tsx b/packages/drip-table-generator/src/layout/preview-table/index.tsx index c39d295..ef2fafc 100644 --- a/packages/drip-table-generator/src/layout/preview-table/index.tsx +++ b/packages/drip-table-generator/src/layout/preview-table/index.tsx @@ -13,12 +13,12 @@ import { GlobalStore } from '@/store'; import styles from './index.module.less'; -interface Props { - driver: DripTableDriver; - customComponents: DripTableProps['components']; +interface Props { + driver: DripTableDriver; + customComponents: DripTableProps['components']; } -const PreviewTable = (props: Props & { store: GlobalStore }) => { +const PreviewTable = (props: Props & { store: GlobalStore }) => { const [state] = props.store; const schema: DripTableSchema = { @@ -28,14 +28,14 @@ const PreviewTable = (props: Props - + diff --git a/packages/drip-table-generator/src/layout/tool-layout/index.tsx b/packages/drip-table-generator/src/layout/tool-layout/index.tsx index 9e546d8..bdb4e73 100644 --- a/packages/drip-table-generator/src/layout/tool-layout/index.tsx +++ b/packages/drip-table-generator/src/layout/tool-layout/index.tsx @@ -30,9 +30,9 @@ const ToolLayout = (props: { store: GlobalStore }) => { }); /** - * 渲染一个Modal用来展示JSON Schema配置 - * @returns {JSX.Element} 返回React组件 - */ + * 渲染一个Modal用来展示JSON Schema配置 + * @returns {JSX.Element} 返回React组件 + */ const renderSchemaModal = () => { if (modalStatus !== 'export' && modalStatus !== 'import') { return null; @@ -109,6 +109,7 @@ const ToolLayout = (props: { store: GlobalStore }) => { globalData.onExportSchema(getSchemaValue()); } } + message.success('复制成功'); setModalStatus(''); setCode(''); }} diff --git a/packages/drip-table-generator/src/store/index.ts b/packages/drip-table-generator/src/store/index.ts index 25a3359..dfa835d 100644 --- a/packages/drip-table-generator/src/store/index.ts +++ b/packages/drip-table-generator/src/store/index.ts @@ -23,7 +23,7 @@ export interface DripTableGeneratorState { currentColumn?: DripTableColumn; globalConfigs: DripTableSchema['configs']; /** 表格数据,generator不需要知道数据格式是什么,直接交给drip-table即可 */ - dataSource: Record[]; + previewDataSource: Record[]; } export const defaultState: () => DripTableGeneratorState = () => ({ @@ -37,7 +37,7 @@ export const defaultState: () => DripTableGeneratorState = () => ({ pagination: false, }, /** 数据 */ - dataSource: [], + previewDataSource: [], }); export type GlobalStore = [DripTableGeneratorState, React.Dispatch>]; @@ -51,7 +51,7 @@ export type GlobalActions = { toggleEditMode: (store?: GlobalStoreObject) => void; editColumns: (store?: GlobalStoreObject) => void; checkColumn: (store?: GlobalStoreObject) => void; - updateDataSource: (store?: GlobalStoreObject) => void; + updatePreviewDataSource: (store?: GlobalStoreObject) => void; updateGlobalConfig: (store?: GlobalStoreObject) => void; } @@ -65,8 +65,8 @@ export const globalActions: GlobalActions = { checkColumn(store) { store?.setState({ ...store.state, currentColumn: store.state.currentColumn ? { ...store.state?.currentColumn } : void 0 }); }, - updateDataSource(store) { - store?.setState({ ...store.state, dataSource: [...store.state.dataSource] }); + updatePreviewDataSource(store) { + store?.setState({ ...store.state, previewDataSource: [...store.state.previewDataSource] }); }, updateGlobalConfig(store) { store?.setState({ ...store.state, globalConfigs: { ...store.state.globalConfigs } }); diff --git a/packages/drip-table-generator/src/typing.ts b/packages/drip-table-generator/src/typing.ts index de5b5d5..bccd03c 100644 --- a/packages/drip-table-generator/src/typing.ts +++ b/packages/drip-table-generator/src/typing.ts @@ -48,19 +48,27 @@ export interface DripTableGeneratorHandler extends DripTableGeneratorState { * @returns { DripTableSchema } 返回DripTableSchema配置 */ getSchemaValue: () => DripTableSchema; + + /** + * 通过接口获取预览用表格数据 + * + * @returns {Record[]} 返回预览用表格数据 + */ + getDataSource: () => Record[]; } -export interface DripTableGeneratorProps { +export interface DripTableGeneratorProps { style?: CSSProperties; - driver?: DripTableDriver; + driver?: DripTableDriver; showComponentLayout?: boolean; componentLayoutStyle?: CSSProperties; rightLayoutStyle?: CSSProperties; showToolLayout?: boolean; - dataSource?: RecordType[]; + /** generator无需关心DataSource数据类型是什么,唯一做的是直接传递给drip-table */ + dataSource?: DripTableRecordTypeBase[]; dataFields?: string[]; schema?: DripTableSchema; - customComponents?: DripTableProps['components']; + customComponents?: DripTableProps['components']; customComponentPanel?: { mode: 'add' | 'replace'; components: DripTableComponentConfig[]; diff --git a/packages/drip-table-generator/src/wrapper.tsx b/packages/drip-table-generator/src/wrapper.tsx index 4711fd4..7b8aecc 100644 --- a/packages/drip-table-generator/src/wrapper.tsx +++ b/packages/drip-table-generator/src/wrapper.tsx @@ -1,5 +1,4 @@ import React, { useState, useImperativeHandle } from 'react'; -import { DripTableRecordTypeBase } from 'drip-table'; import DripTableDriverAntDesign from 'drip-table-driver-antd'; import { useGlobalData } from './hooks'; import { defaultState, DripTableGeneratorState, GlobalStore, setState } from './store'; @@ -12,9 +11,13 @@ import { DripTableGeneratorProps } from './typing'; import styles from './index.module.less'; -const Wrapper = (props: DripTableGeneratorProps & { +export type GeneratorWrapperHandler = { + getState: () => DripTableGeneratorState; +} + +const Wrapper = (props: DripTableGeneratorProps & { store: GlobalStore; -}, ref) => { +}, ref: React.ForwardedRef) => { const { style = {}, driver, @@ -22,12 +25,12 @@ const Wrapper = (props: DripTableGen componentLayoutStyle = {}, rightLayoutStyle = {}, showToolLayout = true, - dataSource = [], + dataSource, schema, customComponentPanel, customComponents, } = useGlobalData(); - const initialData = { dataSource } as DripTableGeneratorState; + const initialData = { previewDataSource: dataSource } as DripTableGeneratorState; if (schema) { initialData.globalConfigs = schema.configs; initialData.columns = schema.columns?.map((item, index) => ({ key: index, sort: index, ...item }));