diff --git a/docs/drip-table-generator/demo/component-settings.ts b/docs/drip-table-generator/demo/component-settings.ts index 8b7fc243f..79ddb92c1 100644 --- a/docs/drip-table-generator/demo/component-settings.ts +++ b/docs/drip-table-generator/demo/component-settings.ts @@ -1,6 +1,7 @@ -import { DataSourceTypeAbbr, DripTableGeneratorProps } from 'drip-table-generator'; +import { DripTableRecordTypeBase, DripTableRecordTypeWithSubtable } from 'drip-table'; +import { DripTableGeneratorProps } from 'drip-table-generator'; -const CustomGeneratorComponentPanel: DripTableGeneratorProps>['customComponentPanel'] = { +const CustomGeneratorComponentPanel: DripTableGeneratorProps>['customComponentPanel'] = { mode: 'add', configs: [ { diff --git a/packages/drip-table-generator/.eslintrc.js b/packages/drip-table-generator/.eslintrc.js index 95fab6d2c..85dc0dfb5 100644 --- a/packages/drip-table-generator/.eslintrc.js +++ b/packages/drip-table-generator/.eslintrc.js @@ -20,6 +20,13 @@ const javascriptRules = { 'unicorn/no-array-reduce': 'off', 'unicorn/prefer-switch': 'off', 'unicorn/explicit-length-check': 'off', + 'react/jsx-curly-spacing': [ + 'error', + { + when: 'always', + attributes: { when: 'never' }, + }, + ], }; const typescriptRules = { diff --git a/packages/drip-table-generator/package.json b/packages/drip-table-generator/package.json index 63f94ee2c..33ad721a2 100755 --- a/packages/drip-table-generator/package.json +++ b/packages/drip-table-generator/package.json @@ -1,6 +1,6 @@ { "name": "drip-table-generator", - "version": "3.2.1-alpha.16", + "version": "3.2.2-alpha.9", "description": "A visualization tool for generating schema of drip-table.", "main": "dist/index.min.js", "module": "lib/index.js", diff --git a/packages/drip-table-generator/src/context/index.ts b/packages/drip-table-generator/src/context/index.ts index ae9c3949a..4ef5122f5 100644 --- a/packages/drip-table-generator/src/context/index.ts +++ b/packages/drip-table-generator/src/context/index.ts @@ -5,11 +5,9 @@ * @modifier : helloqian12138 (johnhello12138@163.com) * @copyright: Copyright (c) 2020 JD Network Technology Co., Ltd. */ -import { DripTableExtraOptions } from 'drip-table'; +import { DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, ExtractDripTableExtraOption } from 'drip-table'; import { createContext } from 'react'; -import { DataSourceTypeAbbr } from '../typing'; - export type DripTableGeneratorStates = Omit; export interface DripTableGeneratorContext { @@ -27,7 +25,7 @@ export interface DripTableGeneratorContext { /** * 表格数据,generator 不解析具体数据结构,仅仅透传给 drip-table */ - previewDataSource: DataSourceTypeAbbr>[]; + previewDataSource: DripTableRecordTypeWithSubtable, 'SubtableDataSourceKey'>>[]; /** * 属性栏类型,根据类型展示不同的抽屉 */ diff --git a/packages/drip-table-generator/src/layouts/attributes-layout/component-configs/index.tsx b/packages/drip-table-generator/src/layouts/attributes-layout/component-configs/index.tsx index 074ebab2c..c7875d779 100644 --- a/packages/drip-table-generator/src/layouts/attributes-layout/component-configs/index.tsx +++ b/packages/drip-table-generator/src/layouts/attributes-layout/component-configs/index.tsx @@ -7,7 +7,7 @@ */ import { ExclamationCircleTwoTone } from '@ant-design/icons'; import { Result } from 'antd'; -import { DripTableExtraOptions } from 'drip-table'; +import { DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, ExtractDripTableExtraOption } from 'drip-table'; import cloneDeep from 'lodash/cloneDeep'; import React from 'react'; @@ -16,10 +16,10 @@ import CustomForm from '@/components/CustomForm'; import { GeneratorContext } from '@/context'; import { DTGTableConfig, TableConfigsContext } from '@/context/table-configs'; import { getColumnItemConfigs, getComponentsConfigs } from '@/layouts/utils'; -import { DataSourceTypeAbbr, DripTableGeneratorProps } from '@/typing'; +import { DripTableGeneratorProps } from '@/typing'; interface ComponentConfigFormProps< - RecordType extends DataSourceTypeAbbr>, + RecordType extends DripTableRecordTypeWithSubtable>, ExtraOptions extends Partial = never, > { customAttributeComponents: DripTableGeneratorProps['customAttributeComponents']; @@ -32,12 +32,12 @@ interface ComponentConfigFormProps< const errorBoundary = (message?: string) => ( } - title={
{ message }
} + title={
{message}
} /> ); function ComponentConfigForm< - RecordType extends DataSourceTypeAbbr>, + RecordType extends DripTableRecordTypeWithSubtable>, ExtraOptions extends Partial = never, >(props: ComponentConfigFormProps) { const { currentColumnID, currentTableID, previewDataSource } = React.useContext(GeneratorContext); @@ -220,7 +220,7 @@ function ComponentConfigForm< }; return ( - { ({ tableConfigs, setTableColumns }) => { + {({ tableConfigs, setTableColumns }) => { const tableIndex = tableConfigs.findIndex(item => item.tableId === currentTableID); const currentColumn = tableConfigs[tableIndex]?.columns.find(item => item.key === currentColumnID); if (!currentColumn) { @@ -248,7 +248,7 @@ function ComponentConfigForm< }} /> ); - } } + }} ); } diff --git a/packages/drip-table-generator/src/layouts/attributes-layout/component-item-config/index.tsx b/packages/drip-table-generator/src/layouts/attributes-layout/component-item-config/index.tsx index d5f3782b7..97b584013 100644 --- a/packages/drip-table-generator/src/layouts/attributes-layout/component-item-config/index.tsx +++ b/packages/drip-table-generator/src/layouts/attributes-layout/component-item-config/index.tsx @@ -9,7 +9,7 @@ import './index.less'; import { ExclamationCircleTwoTone } from '@ant-design/icons'; import { Result } from 'antd'; -import { DripTableExtraOptions } from 'drip-table'; +import { DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, ExtractDripTableExtraOption } from 'drip-table'; import cloneDeep from 'lodash/cloneDeep'; import React from 'react'; @@ -18,12 +18,12 @@ import CustomForm from '@/components/CustomForm'; import { GeneratorContext } from '@/context'; import { DTGTableConfig, TableConfigsContext } from '@/context/table-configs'; import { getColumnItemConfigs, getComponentsConfigs } from '@/layouts/utils'; -import { DataSourceTypeAbbr, DripTableGeneratorProps } from '@/typing'; +import { DripTableGeneratorProps } from '@/typing'; import { getColumnItemByPath, updateColumnItemByPath } from '../utils'; interface ComponentItemConfigFormProps< - RecordType extends DataSourceTypeAbbr>, + RecordType extends DripTableRecordTypeWithSubtable>, ExtraOptions extends Partial = never, > { containerType: 'group' | 'popover'; @@ -38,12 +38,12 @@ const errorBoundary = (message?: string) => ( } - title={
{ message }
} + title={
{message}
} /> ); function ComponentItemConfigForm< - RecordType extends DataSourceTypeAbbr>, + RecordType extends DripTableRecordTypeWithSubtable>, ExtraOptions extends Partial = never, >(props: ComponentItemConfigFormProps) { const { currentColumnID, currentComponentPath, currentTableID, previewDataSource } = React.useContext(GeneratorContext); @@ -210,7 +210,7 @@ function ComponentItemConfigForm< }; return ( - { ({ tableConfigs, setTableColumns }) => { + {({ tableConfigs, setTableColumns }) => { const tableIndex = tableConfigs.findIndex(item => item.tableId === currentTableID); const currentColumn = tableConfigs[tableIndex]?.columns.find(item => item.key === currentColumnID); let currentColumnItem; @@ -251,7 +251,7 @@ function ComponentItemConfigForm< }} /> ); - } } + }} ); } diff --git a/packages/drip-table-generator/src/layouts/attributes-layout/global-configs/index.tsx b/packages/drip-table-generator/src/layouts/attributes-layout/global-configs/index.tsx index cebce93f1..1bb439beb 100644 --- a/packages/drip-table-generator/src/layouts/attributes-layout/global-configs/index.tsx +++ b/packages/drip-table-generator/src/layouts/attributes-layout/global-configs/index.tsx @@ -5,7 +5,7 @@ * @modifier : helloqian12138 (johnhello12138@163.com) * @copyright: Copyright (c) 2020 JD Network Technology Co., Ltd. */ -import { DripTableExtraOptions, DripTableSlotElementSchema } from 'drip-table'; +import { DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, DripTableSlotElementSchema, ExtractDripTableExtraOption } from 'drip-table'; import cloneDeep from 'lodash/cloneDeep'; import React from 'react'; @@ -13,12 +13,12 @@ import { filterAttributes, filterAttributesByRegExp } from '@/utils'; import CustomForm from '@/components/CustomForm'; import { GeneratorContext } from '@/context'; import { DTGTableConfig, TableConfigsContext } from '@/context/table-configs'; -import { DataSourceTypeAbbr, DripTableGeneratorProps, DTGComponentPropertySchema } from '@/typing'; +import { DripTableGeneratorProps, DTGComponentPropertySchema } from '@/typing'; import { GlobalAttrFormConfigs } from './configs'; interface GlobalConfigFormProps< - RecordType extends DataSourceTypeAbbr>, + RecordType extends DripTableRecordTypeWithSubtable>, ExtraOptions extends Partial = never, > { customAttributeComponents: DripTableGeneratorProps['customAttributeComponents']; @@ -28,7 +28,8 @@ interface GlobalConfigFormProps< } function GlobalConfigForm< - RecordType extends DataSourceTypeAbbr>, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, >(props: GlobalConfigFormProps) { const context = React.useContext(GeneratorContext); @@ -373,7 +374,7 @@ function GlobalConfigForm< return ( - { ({ tableConfigs, setTableConfigs }) => { + {({ tableConfigs, setTableConfigs }) => { const currentTableIndex = tableConfigs.findIndex(item => item.tableId === context.currentTableID); return ( ); - } } + }} ); } diff --git a/packages/drip-table-generator/src/layouts/attributes-layout/index.tsx b/packages/drip-table-generator/src/layouts/attributes-layout/index.tsx index 54a623933..2fc8faa63 100644 --- a/packages/drip-table-generator/src/layouts/attributes-layout/index.tsx +++ b/packages/drip-table-generator/src/layouts/attributes-layout/index.tsx @@ -11,12 +11,12 @@ import './index.less'; import { CloseOutlined } from '@ant-design/icons'; import { Button } from 'antd'; import classNames from 'classnames'; -import { DripTableExtraOptions } from 'drip-table'; +import { DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, ExtractDripTableExtraOption } from 'drip-table'; import React from 'react'; import { GeneratorContext } from '@/context'; import { TableConfigsContext } from '@/context/table-configs'; -import { DataSourceTypeAbbr, DripTableGeneratorProps } from '@/typing'; +import { DripTableGeneratorProps } from '@/typing'; import { getComponentsConfigs } from '../utils'; import ComponentConfigForm from './component-configs'; @@ -25,7 +25,7 @@ import GlobalConfigForm from './global-configs'; import { getColumnItemByPath } from './utils'; function AttributesLayout< - RecordType extends DataSourceTypeAbbr>, + RecordType extends DripTableRecordTypeWithSubtable>, ExtraOptions extends Partial = never, >(props: DripTableGeneratorProps) { const body = React.useRef(null); @@ -44,7 +44,7 @@ function AttributesLayout< return ( - { ({ currentTableID, currentColumnID, currentComponentPath, drawerType, setState }) => { + {({ currentTableID, currentColumnID, currentComponentPath, drawerType, setState }) => { const currentTable = tableConfigs.find(item => item.tableId === currentTableID); const currentColumn = currentTable?.columns.find(item => item.key === currentColumnID); const isContainerColumn = currentColumn && (currentColumn.component === 'group' || currentColumn.component === 'popover'); @@ -73,31 +73,31 @@ function AttributesLayout< currentComponentID: void 0, })} /> - { drawerType ? drawerTitleMapper[drawerType] : '' } - { drawerType === 'column' + {drawerType ? drawerTitleMapper[drawerType] : ''} + {drawerType === 'column' ? ( 组件 > - { ' ' } - { getComponentName(currentColumn?.component || '') } + {' '} + {getComponentName(currentColumn?.component || '')} ) - : null } - { drawerType === 'column-item' + : null} + {drawerType === 'column-item' ? ( - { currentColumnItem ? `子组件 > ${getComponentName(currentColumnItem?.component)}` : '' } + {currentColumnItem ? `子组件 > ${getComponentName(currentColumnItem?.component)}` : ''} ) - : null } - { drawerType === 'table' + : null} + {drawerType === 'table' ? ( 表格ID: - { currentTableID } + {currentTableID} ) - : null } + : null}
{ @@ -136,7 +136,7 @@ function AttributesLayout<
); - } } + }}
); } diff --git a/packages/drip-table-generator/src/layouts/index.tsx b/packages/drip-table-generator/src/layouts/index.tsx index 3f89d175f..636056bff 100644 --- a/packages/drip-table-generator/src/layouts/index.tsx +++ b/packages/drip-table-generator/src/layouts/index.tsx @@ -9,18 +9,18 @@ import './index.less'; import { Modal } from 'antd'; import classNames from 'classnames'; -import { DripTableExtraOptions } from 'drip-table'; +import { DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, ExtractDripTableExtraOption } from 'drip-table'; import React from 'react'; import { GeneratorContext } from '@/context'; -import { DataSourceTypeAbbr, DripTableGeneratorProps } from '../typing'; +import { DripTableGeneratorProps } from '../typing'; import AttributesLayout from './attributes-layout'; import TableWorkStation from './table-workstation'; import Toolbar from './toolbar'; function GeneratorLayout< - RecordType extends DataSourceTypeAbbr>, + RecordType extends DripTableRecordTypeWithSubtable>, ExtraOptions extends Partial = never, >(props: DripTableGeneratorProps) { const { drawerType } = React.useContext(GeneratorContext); @@ -29,7 +29,7 @@ function GeneratorLayout< className="jfe-drip-table-generator-layouts-model-container" style={{ ...props.style, width: props.width ?? props.style?.width ?? 1000, height: props.height ?? props.style?.height ?? 640 }} > - { props.showToolbar !== false && } + {props.showToolbar !== false && }
- { props.showAttributeLayout !== false && } + {props.showAttributeLayout !== false && }
), [ @@ -49,7 +49,7 @@ function GeneratorLayout< className="jfe-drip-table-generator-layouts-container" style={{ ...props.style, width: props.width ?? props.style?.width ?? '100%', height: props.height ?? props.style?.height ?? '100%' }} > - { props.showToolbar !== false && } + {props.showToolbar !== false && }
- { props.showAttributeLayout !== false && } + {props.showAttributeLayout !== false && }
) diff --git a/packages/drip-table-generator/src/layouts/table-workstation/components/pagination/index.tsx b/packages/drip-table-generator/src/layouts/table-workstation/components/pagination/index.tsx index 7a1be9e05..09f923c40 100644 --- a/packages/drip-table-generator/src/layouts/table-workstation/components/pagination/index.tsx +++ b/packages/drip-table-generator/src/layouts/table-workstation/components/pagination/index.tsx @@ -7,29 +7,29 @@ */ import { Pagination, PaginationProps } from 'antd'; -import { DripTableColumnSchema, DripTableExtraOptions, DripTableSchema } from 'drip-table'; +import { DripTableColumnSchema, DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, DripTableSchema, ExtractDripTableExtraOption } from 'drip-table'; import React from 'react'; import { safeEvaluate } from '@/utils/sandbox'; -import { DataSourceTypeAbbr, DripTableGeneratorProps } from '@/typing'; +import { DripTableGeneratorProps } from '@/typing'; import { parseReactCSS } from './dom'; export type PaginationComponentProps< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, -CustomColumnSchema extends DripTableColumnSchema = never, -SubtableDataSourceKey extends React.Key = never, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, + CustomColumnSchema extends DripTableColumnSchema = never, + SubtableDataSourceKey extends React.Key = never, > = DripTableSchema['pagination'] & Omit & { renderPagination: DripTableGeneratorProps['renderPagination']; ext?: DripTableExtraOptions['CustomComponentExtraData']; }; function PaginationComponent< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, -CustomColumnSchema extends DripTableColumnSchema = never, -SubtableDataSourceKey extends React.Key = never, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, + CustomColumnSchema extends DripTableColumnSchema = never, + SubtableDataSourceKey extends React.Key = never, >(props: PaginationComponentProps) { if (!props) { return null; } const renderShowTotal = (showTotal?: string | boolean) => { diff --git a/packages/drip-table-generator/src/layouts/table-workstation/components/table-container/index.less b/packages/drip-table-generator/src/layouts/table-workstation/components/table-container/index.less index 04c6a014f..947a9cf4e 100644 --- a/packages/drip-table-generator/src/layouts/table-workstation/components/table-container/index.less +++ b/packages/drip-table-generator/src/layouts/table-workstation/components/table-container/index.less @@ -12,22 +12,30 @@ .@{prefixCls}-wrapper { border: 1px solid transparent; - padding: 0 12px 8px; + padding: 0 12px; width: max-content; position: relative; - min-width: 300px; + min-width: 500px; + display: flex; + flex-direction: column; + overflow-x: auto; + overflow: visible; + background-color: #ffffff; &:hover { border: 1px dashed var(--drip-table-border-color, @border-color); } + &.bordered { + border: 1px dashed #efefef; + } + &.disabled { border: 1px solid transparent; } &.checked { border: 1px solid var(--drip-table-border-color, @border-color); - margin-top: 32px; } } diff --git a/packages/drip-table-generator/src/layouts/table-workstation/components/table-container/index.tsx b/packages/drip-table-generator/src/layouts/table-workstation/components/table-container/index.tsx index 836b390f0..618a006fe 100644 --- a/packages/drip-table-generator/src/layouts/table-workstation/components/table-container/index.tsx +++ b/packages/drip-table-generator/src/layouts/table-workstation/components/table-container/index.tsx @@ -11,17 +11,17 @@ import './index.less'; import { PicLeftOutlined, SettingOutlined } from '@ant-design/icons'; import { AutoComplete, Button, Dropdown, Tooltip } from 'antd'; import classNames from 'classnames'; -import { DripTableExtraOptions } from 'drip-table'; +import { DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, ExtractDripTableExtraOption } from 'drip-table'; import React from 'react'; import { mockId } from '@/utils'; import { DripTableGeneratorContext, GeneratorContext } from '@/context'; import { DTGTableConfig, TableConfigsContext } from '@/context/table-configs'; -import { DataSourceTypeAbbr, DripTableGeneratorProps } from '@/typing'; +import { DripTableGeneratorProps } from '@/typing'; export interface TableContainerProps< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, > { tableConfig: DTGTableConfig; children: React.ReactNode; @@ -57,19 +57,21 @@ function SubTableSetting(props: SubTableSettingProps) { if (dataSource) { fields = Object.keys(dataSource).filter(key => Array.isArray(dataSource[key])); } - } catch {} + } catch { + return []; + } } return fields; }, [context.previewDataSource, context.currentTableID, tableContext.tableConfigs]); return ( - { ({ tableConfigs, updateTableConfig, updateTableConfigs }) => { + {({ tableConfigs, updateTableConfig, updateTableConfigs }) => { const currentTableIndex = tableConfigs.findIndex(item => item.tableId === context.currentTableID); return (
-
{ props.label }
+
{props.label}
); - } } + }} ); } const TableContainer = React.forwardRef(< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, >(props: TableContainerProps, ref: React.ForwardedRef) => { const containerRef = React.useRef(null); + const tableContext = React.useContext(TableConfigsContext); React.useImperativeHandle(ref, () => ({ getContainerWidth: () => containerRef.current?.getBoundingClientRect().width ?? 0, })); @@ -119,17 +122,23 @@ ExtraOptions extends Partial = never, props.tableConfig, ]); + const tableIndex = tableContext.tableConfigs.findIndex(table => table.tableId === props.tableConfig.tableId); + return ( - { ({ currentTableID, drawerType, setState }) => (props.tableTools && props.tableTools.length === 0 + {({ currentTableID, drawerType, setState }) => (props.tableTools && props.tableTools.length === 0 ? ( -
{ props.children }
+
{props.children}
) : (
0, })} + style={{ + marginTop: currentTableID === props.tableConfig.tableId && tableIndex === 0 ? 32 : void 0, + }} ref={containerRef} onClick={(e) => { e.stopPropagation(); @@ -146,66 +155,66 @@ ExtraOptions extends Partial = never, }); }} > - { currentTableID === props.tableConfig.tableId && ( -
- - 表格ID: - { ' ' } - { props.tableConfig.tableId } - -
- { !props.tableTools || props.tableTools.includes('config') - ? ( - - - - ) - : null } - { !props.tableTools || props.tableTools.includes('subtable') - ? ( - - + {currentTableID === props.tableConfig.tableId && ( +
+ + 表格ID: + {' '} + {props.tableConfig.tableId} + +
+ {!props.tableTools || props.tableTools.includes('config') + ? ( + - - ) - : null } + ) + : null} + {!props.tableTools || props.tableTools.includes('subtable') + ? ( + + + + + + ) + : null} +
-
- ) } - { props.children } + )} + {props.children}
- )) } + ))} ); }); diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-footer/index.tsx b/packages/drip-table-generator/src/layouts/table-workstation/editable-footer/index.tsx index 667f077cf..39f6b5eec 100644 --- a/packages/drip-table-generator/src/layouts/table-workstation/editable-footer/index.tsx +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-footer/index.tsx @@ -11,7 +11,7 @@ import './index.less'; import { DownOutlined, PlusOutlined } from '@ant-design/icons'; import { Button, Input, Select } from 'antd'; import classNames from 'classnames'; -import { DripTableExtraOptions, DripTableSlotElementSchema, DripTableTableInformation } from 'drip-table'; +import { DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, DripTableSlotElementSchema, DripTableTableInformation, ExtractDripTableExtraOption } from 'drip-table'; import cloneDeep from 'lodash/cloneDeep'; import React from 'react'; @@ -19,12 +19,12 @@ import RichText from '@/components/RichText'; import { GeneratorContext } from '@/context'; import { DTGTableConfig, DTGTableConfigsContext, TableConfigsContext } from '@/context/table-configs'; import { getSchemaValue } from '@/layouts/utils'; -import { DataSourceTypeAbbr, DripTableGeneratorProps } from '@/typing'; +import { DripTableGeneratorProps } from '@/typing'; import PaginationComponent from '../components/pagination'; interface EditableTableFooterProps< - RecordType extends DataSourceTypeAbbr>, + RecordType extends DripTableRecordTypeWithSubtable>, ExtraOptions extends Partial = never, > { ext: ExtraOptions['CustomComponentExtraData']; @@ -35,7 +35,8 @@ interface EditableTableFooterProps< } function EditableTableFooter< - RecordType extends DataSourceTypeAbbr>, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, >(props: EditableTableFooterProps) { const context = React.useContext(GeneratorContext); @@ -56,7 +57,7 @@ function EditableTableFooter< } if (config.type === 'text') { - return

{ config.text }

; + return

{config.text}

; } if (config.type === 'html') { @@ -66,14 +67,14 @@ function EditableTableFooter< if (config.type === 'search') { return (
- { config.searchKeys && ( + {config.searchKeys && ( - ) } + )} ); } - return { `自定义插槽组件渲染函数 tableProps.slots['${config.slot}'] 不存在` }; + return {`自定义插槽组件渲染函数 tableProps.slots['${config.slot}'] 不存在`}; } if (config.type === 'insert-button') { @@ -112,7 +113,7 @@ function EditableTableFooter< icon={config.showIcon && } style={config.insertButtonStyle} > - { config.insertButtonText } + {config.insertButtonText} ); } @@ -120,7 +121,7 @@ function EditableTableFooter< if (config.type === 'display-column-selector') { return ( ); @@ -150,11 +151,13 @@ function EditableTableFooter< newColumns.splice(index, 1, currentCell); setCurrentCellIndex(-1); setCurrentCell(void 0); - const configs = cloneDeep({ ...globalConfigs, + const configs = cloneDeep({ + ...globalConfigs, footer: { ...globalConfigs.footer, elements: newColumns, - } }); + }, + }); setTableConfigs(configs, 0); } } @@ -162,7 +165,7 @@ function EditableTableFooter< return ( - { ({ tableConfigs, setTableConfigs }) => { + {({ tableConfigs, setTableConfigs }) => { const globalConfigs = tableConfigs[0].configs; const paginationInFooter = typeof globalConfigs.pagination === 'object' && globalConfigs.pagination.position?.startsWith('bottom'); const tableInfo = { @@ -178,24 +181,24 @@ function EditableTableFooter< }; return (
- { paginationInFooter && typeof globalConfigs.pagination === 'object' && ( - { - const configs = { ...globalConfigs }; - if (typeof configs.pagination === 'object') { - configs.pagination.pageSize = size; - } - setTableConfigs(configs, 0); - props.onPageChange?.(current, size, tableInfo); - }} - onChange={(page, pageSize) => props.onPageChange?.(page, pageSize, tableInfo)} - /> - ) } + {paginationInFooter && typeof globalConfigs.pagination === 'object' && ( + { + const configs = { ...globalConfigs }; + if (typeof configs.pagination === 'object') { + configs.pagination.pageSize = size; + } + setTableConfigs(configs, 0); + props.onPageChange?.(current, size, tableInfo); + }} + onChange={(page, pageSize) => props.onPageChange?.(page, pageSize, tableInfo)} + /> + )}
{ typeof globalConfigs.footer === 'object' @@ -217,14 +220,14 @@ function EditableTableFooter< })} style={{ width: Number(element.span) ? `${(Number(element.span) * 100) / 24}%` : void 0, ...element.style }} > - { renderColumnContent(element) } + {renderColumnContent(element)}
)) }
); - } } + }} ); } diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-header/index.tsx b/packages/drip-table-generator/src/layouts/table-workstation/editable-header/index.tsx index 55f117ce4..837b2d268 100644 --- a/packages/drip-table-generator/src/layouts/table-workstation/editable-header/index.tsx +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-header/index.tsx @@ -11,7 +11,7 @@ import './index.less'; import { DownOutlined, PlusOutlined } from '@ant-design/icons'; import { Button, Input, Select } from 'antd'; import classNames from 'classnames'; -import { DripTableExtraOptions, DripTableSlotElementSchema, DripTableTableInformation } from 'drip-table'; +import { DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, DripTableSlotElementSchema, DripTableTableInformation, ExtractDripTableExtraOption } from 'drip-table'; import cloneDeep from 'lodash/cloneDeep'; import React from 'react'; @@ -19,12 +19,12 @@ import RichText from '@/components/RichText'; import { GeneratorContext } from '@/context'; import { DTGTableConfig, DTGTableConfigsContext, TableConfigsContext } from '@/context/table-configs'; import { getSchemaValue } from '@/layouts/utils'; -import { DataSourceTypeAbbr, DripTableGeneratorProps } from '@/typing'; +import { DripTableGeneratorProps } from '@/typing'; import PaginationComponent from '../components/pagination'; interface EditableTableHeaderProps< - RecordType extends DataSourceTypeAbbr>, + RecordType extends DripTableRecordTypeWithSubtable>, ExtraOptions extends Partial = never, > { ext: ExtraOptions['CustomComponentExtraData']; @@ -35,7 +35,8 @@ interface EditableTableHeaderProps< } function EditableTableHeader< - RecordType extends DataSourceTypeAbbr>, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, >(props: EditableTableHeaderProps) { const context = React.useContext(GeneratorContext); @@ -56,7 +57,7 @@ function EditableTableHeader< } if (config.type === 'text') { - return

{ config.text }

; + return

{config.text}

; } if (config.type === 'html') { @@ -66,14 +67,14 @@ function EditableTableHeader< if (config.type === 'search') { return (
- { config.searchKeys && ( + {config.searchKeys && ( - ) } + )} ); } - return { `自定义插槽组件渲染函数 tableProps.slots['${config.slot}'] 不存在` }; + return {`自定义插槽组件渲染函数 tableProps.slots['${config.slot}'] 不存在`}; } if (config.type === 'insert-button') { @@ -112,7 +113,7 @@ function EditableTableHeader< icon={config.showIcon && } style={config.insertButtonStyle} > - { config.insertButtonText } + {config.insertButtonText} ); } @@ -120,7 +121,7 @@ function EditableTableHeader< if (config.type === 'display-column-selector') { return ( ); @@ -150,11 +151,13 @@ function EditableTableHeader< newColumns.splice(index, 1, currentCell); setCurrentCellIndex(-1); setCurrentCell(void 0); - const configs = cloneDeep({ ...globalConfigs, + const configs = cloneDeep({ + ...globalConfigs, header: { ...globalConfigs.header, elements: newColumns, - } }); + }, + }); setTableConfigs(configs, 0); } } @@ -162,7 +165,7 @@ function EditableTableHeader< return ( - { ({ tableConfigs, setTableConfigs }) => { + {({ tableConfigs, setTableConfigs }) => { const globalConfigs = tableConfigs[0].configs; const paginationInHeader = typeof globalConfigs.pagination === 'object' && globalConfigs.pagination.position?.startsWith('top'); const tableInfo = { @@ -178,7 +181,7 @@ function EditableTableHeader< }; return (
- { paginationInHeader && typeof globalConfigs.pagination === 'object' && ( + {paginationInHeader && typeof globalConfigs.pagination === 'object' && ( - ) } + )}
{ typeof globalConfigs.header === 'object' @@ -216,14 +219,14 @@ function EditableTableHeader< })} style={{ width: Number(element.span) ? `${(Number(element.span) * 100) / 24}%` : void 0, ...element.style }} > - { renderColumnContent(element) } + {renderColumnContent(element)}
)) }
); - } } + }} ); } diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/add-column/index.less b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/add-column/index.less new file mode 100644 index 000000000..3e1d0a348 --- /dev/null +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/add-column/index.less @@ -0,0 +1,48 @@ +/** + * This file is part of the drip-table project. + * @link : https://drip-table.jd.com/ + * @author : helloqian12138 (johnhello12138@163.com) + * @modifier : helloqian12138 (johnhello12138@163.com) + * @copyright: Copyright (c) 2020 JD Network Technology Co., Ltd. + */ + +@import url("../../../../../styles/index.less"); + +@prefixCls: jfe-drip-table-generator-workstation-table-header; + +.@{prefixCls}-add-item { + color: #000000d9; + font-weight: 500; + background: #f5f5f5; + border-top: 1px solid transparent; + border-bottom: 1px solid #e0e0e0; + transition: all .3s ease; + height: 48px; + padding: 0 12px; + min-width: 120px; + text-align: center; + display: flex; + justify-content: center; + align-items: center; + + &.small { + height: 35px; + padding: 0 8px; + } + + &.middle, + &.default { + height: 48px; + padding: 0 12px; + } + + &.large { + height: 56px; + padding: 0 16px; + } + + &.sticky { + position: sticky; + top: 0; + } +} diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/add-column/index.tsx b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/add-column/index.tsx new file mode 100644 index 000000000..36357bcf6 --- /dev/null +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/add-column/index.tsx @@ -0,0 +1,84 @@ +/** + * This file is part of the drip-table project. + * @link : https://drip-table.jd.com/ + * @author : helloqian12138 (johnhello12138@163.com) + * @modifier : helloqian12138 (johnhello12138@163.com) + * @copyright: Copyright (c) 2020 JD Network Technology Co., Ltd. + */ +import './index.less'; + +import { PlusOutlined } from '@ant-design/icons'; +import { Button, Dropdown } from 'antd'; +import classNames from 'classnames'; +import { DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, ExtractDripTableExtraOption } from 'drip-table'; +import React from 'react'; + +import { DTGTableConfig } from '@/context/table-configs'; +import { DripTableGeneratorProps } from '@/typing'; + +import ComponentsSelector from '../components-selector'; + +interface ColumnHeaderListProps< + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, +> { + tableConfig: DTGTableConfig; + customComponentPanel?: DripTableGeneratorProps['customComponentPanel']; + customColumnAddPanel?: DripTableGeneratorProps['customColumnAddPanel']; + onColumnAdded?: DripTableGeneratorProps['onColumnAdded']; +} + +function AddColumnComponent< + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, +>(props: ColumnHeaderListProps) { + const [dropdownOpen, setDropdownOpen] = React.useState(false); + + const DropdownRender = React.useCallback(() => ( + setDropdownOpen(false)} + onColumnAdded={props.onColumnAdded} + /> + ), [ + dropdownOpen, + props.tableConfig.tableId, + props.customComponentPanel, + props.customColumnAddPanel, + setDropdownOpen, + props.onColumnAdded, + ]); + + return ( +
+ { if (!open) { setDropdownOpen(false); } }} + dropdownRender={DropdownRender} + > +
+ ); +} + +export default AddColumnComponent; diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/cell/cell.tsx b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/cell/cell.tsx index 504c39d5f..092ffaac4 100644 --- a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/cell/cell.tsx +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/cell/cell.tsx @@ -9,23 +9,21 @@ import './index.less'; import { Alert } from 'antd'; import { - DripTableExtraOptions, + DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, ExtractDripTableExtraOption, } from 'drip-table'; import React from 'react'; -import { DataSourceTypeAbbr } from '@/typing'; - import CommonCell, { CommonCellProps } from './common'; import GroupCell, { GroupCellProps } from './group'; import PopoverCell, { PopoverCellProps } from './popover'; export type TableCellProps< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, > = PopoverCellProps | GroupCellProps | CommonCellProps function CellComponent< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, >(props: TableCellProps) { if (props.column?.component === 'group') { return } />; diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/cell/common.tsx b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/cell/common.tsx index 2b62441d9..18fbb209a 100644 --- a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/cell/common.tsx +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/cell/common.tsx @@ -13,16 +13,19 @@ import { DripTableBuiltInColumnSchema, DripTableExtraOptions, DripTableProps, + DripTableRecordTypeBase, + DripTableRecordTypeWithSubtable, + ExtractDripTableExtraOption, TABLE_LAYOUT_COLUMN_RENDER_GENERATOR_DO_NOT_USE_IN_PRODUCTION as columnRenderGenerator, } from 'drip-table'; import React from 'react'; import { filterAttributes } from '@/utils'; import { createEvaluator, evaluate, finalizeString, safeEvaluate } from '@/utils/sandbox'; -import { DataSourceTypeAbbr, DripTableGeneratorProps } from '@/typing'; +import { DripTableGeneratorProps } from '@/typing'; export interface CommonCellProps< - RecordType extends DataSourceTypeAbbr>, + RecordType extends DripTableRecordTypeWithSubtable>, ExtraOptions extends Partial = never, > { column: DripTableBuiltInColumnSchema; @@ -50,7 +53,7 @@ const generatorComponentSchema = ); function CommonCell< - RecordType extends DataSourceTypeAbbr>, + RecordType extends DripTableRecordTypeWithSubtable>, ExtraOptions extends Partial = never, >(props: CommonCellProps) { if (props.column?.component === 'group' || props.column?.component === 'popover') { @@ -84,7 +87,7 @@ function CommonCell< : () =>
; return ( - { renderCommonCell(null, { type: 'body', key: '$$KEY$$', record: props.record, index: props.rowIndex }, props.rowIndex) } + {renderCommonCell(null, { type: 'body', key: '$$KEY$$', record: props.record, index: props.rowIndex }, props.rowIndex)} ); } diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/cell/group.tsx b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/cell/group.tsx index b13456a58..5f8657c75 100644 --- a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/cell/group.tsx +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/cell/group.tsx @@ -14,19 +14,22 @@ import classNames from 'classnames'; import { DripTableBuiltInColumnSchema, DripTableExtraOptions, + DripTableRecordTypeBase, + DripTableRecordTypeWithSubtable, + ExtractDripTableExtraOption, } from 'drip-table'; import React from 'react'; import { GeneratorContext } from '@/context'; import { DTGTableConfig } from '@/context/table-configs'; -import { DataSourceTypeAbbr, DripTableGeneratorProps } from '@/typing'; +import { DripTableGeneratorProps } from '@/typing'; import ComponentsSelector from '../components-selector'; import CellComponent from './cell'; import { CommonCellProps } from './common'; export interface GroupCellProps< - RecordType extends DataSourceTypeAbbr>, + RecordType extends DripTableRecordTypeWithSubtable>, ExtraOptions extends Partial = never, > extends CommonCellProps { column: DripTableBuiltInColumnSchema; @@ -48,7 +51,8 @@ export interface GroupCellProps< const getIndex = (layout: number[], rowIndex: number, colIndex: number) => layout.slice(0, rowIndex).reduce((prev, curr) => prev + curr, 0) + colIndex; function GroupCell< - RecordType extends DataSourceTypeAbbr>, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, >(props: GroupCellProps) { const [dropDownIndex, setDropDownIndex] = React.useState([] as (number | 'content' | 'popover')[]); @@ -88,7 +92,7 @@ function GroupCell< onClick={e => e.stopPropagation()} >
- { options.layout.map((colLength, rowIndex) => ( + {options.layout.map((colLength, rowIndex) => ( - { Array.from({ length: colLength }, (v, i) => i).map((col, colIndex) => { + {Array.from({ length: colLength }, (v, i) => i).map((col, colIndex) => { const componentIndex = getIndex(options.layout, rowIndex, colIndex); const itemColumn = options.items[componentIndex] ?? null; const itemColumnSchema = itemColumn && 'component' in itemColumn ? itemColumn : itemColumn?.schema; @@ -123,7 +127,7 @@ function GroupCell< }); }} > - { itemColumnSchema && itemColumnSchema.key === currentComponentID && ( + {itemColumnSchema && itemColumnSchema.key === currentComponentID && (
- ) } - { itemColumnSchema + )} + {itemColumnSchema ? ( 点击添加子组件
- ) } + )} ); - }) } + })} - )) } + ))}
diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/cell/index.tsx b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/cell/index.tsx index 475b035ef..e30ecd19c 100644 --- a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/cell/index.tsx +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/cell/index.tsx @@ -11,6 +11,9 @@ import { DripTableBuiltInColumnSchema, DripTableExtraOptions, DripTableProps, + DripTableRecordTypeBase, + DripTableRecordTypeWithSubtable, + ExtractDripTableExtraOption, } from 'drip-table'; import React from 'react'; @@ -18,14 +21,14 @@ import { GeneratorContext } from '@/context'; import { DTGTableConfig, TableConfigsContext } from '@/context/table-configs'; import { getColumnItemByPath, updateColumnItemByPath } from '@/layouts/attributes-layout/utils'; import { getSchemaValue } from '@/layouts/utils'; -import { DataSourceTypeAbbr, DripTableGeneratorProps } from '@/typing'; +import { DripTableGeneratorProps } from '@/typing'; import CellComponent from './cell'; import { GroupCellProps } from './group'; import { PopoverCellProps } from './popover'; interface TableCellProps< - RecordType extends DataSourceTypeAbbr>, + RecordType extends DripTableRecordTypeWithSubtable>, ExtraOptions extends Partial = never, > { column: DripTableBuiltInColumnSchema; @@ -50,13 +53,13 @@ interface TableCellProps< } function TableCell< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, >(props: TableCellProps) { const { tableConfigs } = React.useContext(TableConfigsContext); return ( - { ({ setTableColumns }) => { + {({ setTableColumns }) => { const onChangeColumnItem: PopoverCellProps['onChangeColumnItem'] = (path, schema, tableIndex) => { const newColumns = [...props.tableConfig.columns]; const newColumn = updateColumnItemByPath(newColumns[props.columnIndex], path, schema); @@ -102,7 +105,7 @@ ExtraOptions extends Partial = never, }; return ( - { ({ setState }) => ( + {({ setState }) => ( = never, }); }} /> - ) } + )} ); - } } + }} ); } diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/cell/popover.tsx b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/cell/popover.tsx index 895296c16..8559e07c6 100644 --- a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/cell/popover.tsx +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/cell/popover.tsx @@ -15,20 +15,23 @@ import { DripTableBuiltInColumnSchema, DripTableExtraOptions, DripTableProps, + DripTableRecordTypeBase, + DripTableRecordTypeWithSubtable, + ExtractDripTableExtraOption, } from 'drip-table'; import React from 'react'; import { GeneratorContext } from '@/context'; import { DTGTableConfig } from '@/context/table-configs'; -import { DataSourceTypeAbbr, DripTableGeneratorProps } from '@/typing'; +import { DripTableGeneratorProps } from '@/typing'; import ComponentsSelector from '../components-selector'; import CellComponent from './cell'; import { CommonCellProps } from './common'; export interface PopoverCellProps< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never,> extends CommonCellProps { + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never,> extends CommonCellProps { column: DripTableBuiltInColumnSchema; path: (number | 'popover' | 'content')[]; onChangeColumnItem: (path: (number | 'popover' | 'content')[], schema: DripTableBuiltInColumnSchema, tableIndex: number) => void; @@ -45,8 +48,8 @@ ExtraOptions extends Partial = never,> extends CommonCell } function PopoverCell< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never,>(props: PopoverCellProps) { + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never,>(props: PopoverCellProps) { const [dropDown, setDropDown] = React.useState(false); const [popoverDropDown, setPopoverDropDown] = React.useState(false); const { currentComponentID } = React.useContext(GeneratorContext); @@ -113,25 +116,25 @@ ExtraOptions extends Partial = never,>(props: PopoverCell }); }} > - { options.popover.key === currentComponentID && ( - { if (!open) { setPopoverDropDown(false); } }} - dropdownRender={DropdownRender1} - > -
- - { - e.stopPropagation(); - setPopoverDropDown(true); - }} - /> - -
-
- ) } + {options.popover.key === currentComponentID && ( + { if (!open) { setPopoverDropDown(false); } }} + dropdownRender={DropdownRender1} + > +
+ + { + e.stopPropagation(); + setPopoverDropDown(true); + }} + /> + +
+
+ )} = never,>(props: PopoverCell }); }} > - { options.content.key === currentComponentID && ( - { if (!open) { setDropDown(false); } }} - dropdownRender={DropdownRender2} - > -
- - { - e.stopPropagation(); - setDropDown(true); - }} - /> - -
-
- ) } + {options.content.key === currentComponentID && ( + { if (!open) { setDropDown(false); } }} + dropdownRender={DropdownRender2} + > +
+ + { + e.stopPropagation(); + setDropDown(true); + }} + /> + +
+
+ )} >, -ExtraOptions extends Partial = never, ->{ +export interface ColumnHeaderProps< + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, +> { tableConfig: DTGTableConfig; renderHeaderCellFilter: DripTableGeneratorProps['renderHeaderCellFilter']; column: DTGTableConfig['columns'][number]; @@ -26,8 +26,8 @@ ExtraOptions extends Partial = never, } export function FilterViewer< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, >(props: ColumnHeaderProps) { const tableContext = React.useContext(TableConfigsContext); const [filteredValue, setFilteredValue] = React.useState(props.column.defaultFilteredValue || []); @@ -47,20 +47,20 @@ ExtraOptions extends Partial = never, } return ( - { ({ setState }) => ( + {({ setState }) => ( setFilteredValue(checkedValues as React.Key[])} > - { props.column.filters?.map((item, index) => ( + {props.column.filters?.map((item, index) => ( - { item.text } + {item.text} - )) } + ))} - )} + )} icon={null} cancelText="重置" okText="确认" @@ -87,7 +87,7 @@ ExtraOptions extends Partial = never, > - ) } + )} ); } diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/column-header/index.less b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/column-header/index.less index d6896f5ac..382168054 100644 --- a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/column-header/index.less +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/column-header/index.less @@ -23,6 +23,7 @@ min-width: 120px; text-align: center; position: relative; + display: flex; &.large { padding: 0 16px; diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/column-header/index.tsx b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/column-header/index.tsx index 03eae39bb..a8db91d10 100644 --- a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/column-header/index.tsx +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/column-header/index.tsx @@ -10,7 +10,7 @@ import './index.less'; import { ArrowLeftOutlined, ArrowRightOutlined, CaretDownOutlined, CaretUpOutlined, CopyOutlined, DeleteOutlined, EllipsisOutlined, QuestionCircleOutlined, SettingOutlined } from '@ant-design/icons'; import { Alert, Button, Dropdown, MenuProps, message, Popconfirm, Popover, Tooltip } from 'antd'; import classNames from 'classnames'; -import { DripTableExtraOptions } from 'drip-table'; +import { DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, ExtractDripTableExtraOption } from 'drip-table'; import React from 'react'; import ClipboardButton from 'react-clipboard.js'; @@ -18,15 +18,16 @@ import { formatNumber } from '@/utils'; import RichText from '@/components/RichText'; import { GeneratorContext } from '@/context'; import { DTGTableConfig, TableConfigsContext } from '@/context/table-configs'; -import { DataSourceTypeAbbr, DripTableGeneratorProps } from '@/typing'; +import { DripTableGeneratorProps } from '@/typing'; import ComponentsSelector from '../components-selector'; import { FilterViewer } from './filter'; -export interface ColumnHeaderProps < -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, ->{ +export interface ColumnHeaderProps< + RecordType extends DripTableRecordTypeWithSubtable>, + + ExtraOptions extends Partial = never, +> { tableConfig: DTGTableConfig; column: DTGTableConfig['columns'][number]; containerWidth: number; @@ -41,8 +42,9 @@ ExtraOptions extends Partial = never, renderHeaderCellFilter: DripTableGeneratorProps['renderHeaderCellFilter']; } function ColumnHeader< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, + RecordType extends DripTableRecordTypeWithSubtable>, + + ExtraOptions extends Partial = never, >(props: ColumnHeaderProps) { const [selector, setSelector] = React.useState(''); const columnTitle = React.useMemo(() => { @@ -187,7 +189,7 @@ ExtraOptions extends Partial = never, return ( - { ({ currentComponentPath, currentColumnID, currentComponentID, currentTableID, drawerType, setState }) => ( + {({ currentComponentPath, currentColumnID, currentComponentID, currentTableID, drawerType, setState }) => (
= never, onMouseEnter={() => setState({ currentHoverColumnID: props.column.key })} onMouseLeave={() => setState({ currentHoverColumnID: void 0 })} > - { props.tableConfig.tableId === currentTableID && props.column.key === currentColumnID && ( + {props.tableConfig.tableId === currentTableID && props.column.key === currentColumnID && ( - { ({ tableConfigs, setTableColumns }) => ( + {({ tableConfigs, setTableColumns }) => (
e.stopPropagation()}> - { (!props.columnTools || props.columnTools.includes('config')) && ( - -
- ) } + )}
- ) } + )}
0 ? columnTitleWidth : '100%', textAlign: props.column.align, - display: 'inline-block', + display: 'flex', }} > - { props.column.description && ( + {props.column.description && ( }> - ) } + )}
{ columnRightCount > 0 && (
- { props.column.sorter && ( - )}> - { props.column.sortDirections?.length === 1 && props.column.sortDirections[0] === 'ascend' && ( - - ) } - { props.column.sortDirections?.length === 1 && props.column.sortDirections[0] === 'descend' && ( - - ) } - { (!props.column.sortDirections || props.column.sortDirections?.length !== 1) && ( - - - - - ) } - - ) } - { props.column.filters && props.column.filters.length > 0 && ( + {props.column.sorter && ( + )}> + {props.column.sortDirections?.length === 1 && props.column.sortDirections[0] === 'ascend' && ( + + )} + {props.column.sortDirections?.length === 1 && props.column.sortDirections[0] === 'descend' && ( + + )} + {(!props.column.sortDirections || props.column.sortDirections?.length !== 1) && ( + + + + + )} + + )} + {props.column.filters && props.column.filters.length > 0 && ( - ) } + )}
) }
- ) } + )}
); } diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/components-selector/index.tsx b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/components-selector/index.tsx index 8fb8147b1..d3902d8ef 100644 --- a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/components-selector/index.tsx +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/components-selector/index.tsx @@ -8,20 +8,20 @@ import './index.less'; import { Button, Input, message } from 'antd'; -import { DripTableExtraOptions } from 'drip-table'; +import { DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, ExtractDripTableExtraOption } from 'drip-table'; import React from 'react'; import { filterAttributes, mockId } from '@/utils'; import { DTGTableConfig, TableConfigsContext } from '@/context/table-configs'; import { getComponentsConfigs, getGroups, getSchemaValue } from '@/layouts/utils'; -import { DataSourceTypeAbbr, DripTableComponentAttrConfig, DripTableGeneratorProps } from '@/typing'; +import { DripTableComponentAttrConfig, DripTableGeneratorProps } from '@/typing'; import Selector from './selector'; interface ComponentsSelectorProps< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, ->{ + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, +> { tableId: string; showTitle?: boolean; showFilter?: boolean; @@ -65,8 +65,8 @@ const getColumnSchemaByComponent = (component: DripTableComponentAttrConfig, tit }; function ComponentsSelector< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, >(props: ComponentsSelectorProps) { const [groups, setGroups] = React.useState(getGroups(props.customComponentPanel)); const [components, setComponents] = React.useState(getComponentsConfigs('', props.customComponentPanel, 'ComponentsSelector')); @@ -88,23 +88,23 @@ ExtraOptions extends Partial = never, return ( - { ({ tableConfigs, setTableColumns }) => (props.customColumnAddPanel + {({ tableConfigs, setTableColumns }) => (props.customColumnAddPanel ? props.customColumnAddPanel({ tableConfig: tableConfigs.find(c => c.tableId === props.tableId), components, }) : (
e.stopPropagation()}> - { props.showTitle && ( -
- { setTitle(e.target.value); }} - /> -
- ) } + {props.showTitle && ( +
+ { setTitle(e.target.value); }} + /> +
+ )} = never, setComponentConfig(component); }} /> - { componentConfig?.['ui:type'] === 'popover' && ( + {componentConfig?.['ui:type'] === 'popover' && (
浮窗组件
= never, }} />
- ) } - { componentConfig?.['ui:type'] === 'popover' && ( + )} + {componentConfig?.['ui:type'] === 'popover' && (
单元格内组件
= never, />
- ) } + )}
- )) } + ))}
); diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/header-list/index.less b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/header-list/index.less index 1aa5a0cb2..2e55cc6b4 100644 --- a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/header-list/index.less +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/header-list/index.less @@ -101,3 +101,8 @@ display: none; } } + +.@{prefixCls}-left-fixed-part { + position: sticky; + left: 0; +} diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/header-list/index.tsx b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/header-list/index.tsx index c073c3c0b..cacca9109 100644 --- a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/header-list/index.tsx +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/header-list/index.tsx @@ -10,23 +10,21 @@ import './index.less'; import { PlusOutlined } from '@ant-design/icons'; import { Button, Checkbox, Dropdown } from 'antd'; import classNames from 'classnames'; -import { DripTableExtraOptions } from 'drip-table'; +import { DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, ExtractDripTableExtraOption } from 'drip-table'; import React from 'react'; import { ReactSortable } from 'react-sortablejs'; import { filterArray } from '@/utils'; import { DTGTableConfig } from '@/context/table-configs'; -import { DataSourceTypeAbbr, DripTableGeneratorProps } from '@/typing'; +import { DripTableGeneratorProps } from '@/typing'; import ColumnHeader from '../column-header'; import ComponentsSelector from '../components-selector'; interface ColumnHeaderListProps< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, > { - scrollTarget: string; - scrollLeft: number; tableConfig: DTGTableConfig; containerWidth: number; draggable: DripTableGeneratorProps['draggable']; @@ -36,14 +34,13 @@ ExtraOptions extends Partial = never, customColumnAddPanel?: DripTableGeneratorProps['customColumnAddPanel']; onColumnAdded?: DripTableGeneratorProps['onColumnAdded']; onResort: (column: DTGTableConfig['columns']) => void; - onScroll: (scrollLeft: number) => void; onClick: DripTableGeneratorProps['onClick']; renderHeaderCellFilter: DripTableGeneratorProps['renderHeaderCellFilter']; } function ColumnHeaderList< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, >(props: ColumnHeaderListProps) { const scrollableRow = React.useRef(null); const [dropdownOpen, setDropdownOpen] = React.useState(false); @@ -55,11 +52,6 @@ ExtraOptions extends Partial = never, leftFixedColumns = filterArray(columnList, item => item.column.fixed === 'left' || (item.column.fixed && item.id < sortableColumns[0].id)); rightFixedColumns = filterArray(columnList, item => item.column.fixed === 'right' || (item.column.fixed && item.id > sortableColumns[0].id)); } - React.useEffect(() => { - if (scrollableRow.current && props.scrollTarget !== '') { - scrollableRow.current.scrollLeft = props.scrollLeft; - } - }, [props.scrollLeft, props.scrollTarget]); const DropdownRender = React.useCallback(() => ( = never, [props.tableConfig.configs.size || 'default']: props.tableConfig.configs.size, })} > - { props.tableConfig.hasSubTable && ( + {props.tableConfig.hasSubTable && (
= never, })} style={{ width: 48, minWidth: 48 }} /> - ) } - { props.tableConfig.configs.rowSelection && ( + )} + {props.tableConfig.configs.rowSelection && (
= never, >
- ) } - { leftFixedColumns.length > 0 - ? leftFixedColumns.map((columnWrapper, index) => ( - - )) - : null } + )} + {leftFixedColumns.length > 0 + ? ( +
+ {leftFixedColumns.map((columnWrapper, index) => ( + + ))} +
+ ) + : null}
= never, overflowX: props.tableConfig.configs.scroll?.x ? 'auto' : void 0, overflowY: 'hidden', }} - onScroll={(e) => { if (!props.scrollTarget) { props.onScroll((e.target as HTMLDivElement).scrollLeft); } }} > = never, }} style={{ display: 'flex' }} > - { sortableColumns.map(columnWrapper => ( + {sortableColumns.map(columnWrapper => ( = never, renderHeaderCellFilter={props.renderHeaderCellFilter} containerWidth={props.containerWidth} /> - )) } + ))}
- { rightFixedColumns.length > 0 + {rightFixedColumns.length > 0 ? rightFixedColumns.map((columnWrapper, index) => ( = never, containerWidth={props.containerWidth} /> )) - : null } + : null}
.@{prefixCls}-row { + display: flex; + width: 100%; + + &.stripe { + background-color: #efefef; + } + } + + & > .@{prefixCls}-header { + background: #dddddd; + font-weight: bold; + + &.sticky { + position: sticky; + top: 0; + z-index: 10; + } + + &.invisible { + .@{prefixCls}-header-item { + opacity: .7; + background: + linear-gradient( + 45deg, + var(--drip-table-background-color, @background-color) 0, + var(--drip-table-background-color, @background-color) 10%, + transparent 10%, + transparent 20%, + var(--drip-table-background-color, @background-color) 20%, + var(--drip-table-background-color, @background-color) 30%, + transparent 30%, + transparent 40%, + var(--drip-table-background-color, @background-color) 40%, + var(--drip-table-background-color, @background-color) 50%, + transparent 50%, + transparent 60%, + var(--drip-table-background-color, @background-color) 60%, + var(--drip-table-background-color, @background-color) 70%, + transparent 70%, + transparent 80%, + var(--drip-table-background-color, @background-color) 80%, + var(--drip-table-background-color, @background-color) 90%, + transparent 90%, + transparent 100% + ); + } + } + } +} + +.@{prefixCls}-header-item { + color: #000000d9; + font-weight: 500; + background: #f5f5f5; + border: 1px solid transparent; + border-bottom: 1px solid #e0e0e0; + transition: all .3s ease; + height: 48px; + padding: 0 12px; + line-height: 48px; + min-width: 120px; + text-align: center; + position: relative; + display: flex; + + &.large { + padding: 0 16px; + height: 56px; + line-height: 56px; + } + + &.middle, + &.default { + padding: 0 12px; + height: 48px; + line-height: 48px; + } + + &.small { + padding: 0 8px; + height: 35px; + line-height: 35px; + } + + &.bordered { + border-right: 1px solid #e0e0e0; + } + + &:hover { + border: 1px dashed var(--drip-table-border-color, @border-color); + border-bottom: 1px solid #e0e0e0; + + &.disabled { + border: 1px solid transparent; + } + } + + &.checked { + border: 1px solid var(--drip-table-border-color, @border-color); + border-bottom: 1px solid #e0e0e0; + + > .@{prefixCls}-tools { + top: 0; + } + } + + &.right-shadow { + box-shadow: 0 0 4px 0 #ffffff, 4px 0 2px -2px rgb(0 0 0 / 32%); + margin-right: 3px; + margin-left: 1px; + } + + &.left-shadow { + box-shadow: 0 0 4px 0 #ffffff, -4px 0 2px -2px rgb(0 0 0 / 32%); + margin-left: 4px; + } +} diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/left-columns/index.tsx b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/left-columns/index.tsx new file mode 100644 index 000000000..26fe004df --- /dev/null +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/left-columns/index.tsx @@ -0,0 +1,261 @@ +/** + * This file is part of the drip-table project. + * @link : https://drip-table.jd.com/ + * @author : helloqian12138 (johnhello12138@163.com) + * @modifier : helloqian12138 (johnhello12138@163.com) + * @copyright: Copyright (c) 2020 JD Network Technology Co., Ltd. + */ +import './index.less'; + +import { PlusSquareOutlined } from '@ant-design/icons'; +import { Checkbox } from 'antd'; +import classNames from 'classnames'; +import { DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, DripTableTableInformation, ExtractDripTableExtraOption } from 'drip-table'; +import React from 'react'; + +import { formatNumber, mockId } from '@/utils'; +import { DTGTableConfig, TableConfigsContext } from '@/context/table-configs'; +import { DripTableGeneratorProps } from '@/typing'; + +import EditableTable from '../..'; +import ColumnHeader from '../column-header'; +import { RightFixedColumnsHandler } from '../right-columns'; +import { ScrollableColumnsHandler } from '../scroll-columns'; +import TableSection from '../table-section'; + +export interface LeftFixedColumnsProps< + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never +> extends DripTableGeneratorProps { + tableConfig: DTGTableConfig; + previewDataSource: ({ id: number; record: RecordType })[]; + containerWidth: number; + siblings: [React.RefObject, React.RefObject]; + columnList: { id: number; column: DTGTableConfig['columns'][number] }[]; + ref?: React.RefObject; + rowHeaderHeights?: number[]; +} + +export interface LeftFixedColumnsHandler { + getRowHeight: () => number; + getSubTableHeight: () => number[]; +} + +function LeftFixedColumnsInner< + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never +>( + props: LeftFixedColumnsProps, + ref: React.ForwardedRef, +) { + const { tableConfigs } = React.useContext(TableConfigsContext); + const currentTableIndex = tableConfigs.findIndex(c => c.tableId === props.tableConfig.tableId); + const [rowHeight, setRowHeight] = React.useState(void 0 as number | undefined); + const rowRef = React.createRef(); + const containerRef = React.createRef(); + + const leftMargins = React.useMemo(() => { + let margin = 0; + if (props.tableConfig.hasSubTable) { + margin += props.tableConfig.configs.bordered ? 50 : 48; + } + if (props.tableConfig.configs.rowSelection) { + margin += props.tableConfig.configs.bordered ? 49 : 48; + } + for (let i = 0; i < props.columnList.length; i++) { + const column = props.columnList[i].column; + const width = column.width ? formatNumber(String(column.width).replace('px', '').replace('%', '') || 200) as number : 200; + margin += Math.max(width, 120); + } + if (props.columnList.length > 0 && !props.tableConfig.configs.bordered) { + margin += 3; + } + return margin; + }, [props.tableConfig.hasSubTable, props.tableConfig.configs, props.columnList]); + + const getCurrentRowHeight = () => { + let maxCellHeight = 0; + const currentRowHeight = rowRef.current?.offsetHeight ?? 0; + for (const element of (rowRef.current?.children || []) as HTMLDivElement[]) { + if (element.children[0]) { + const trueCellHeight = (element.children[0] as HTMLDivElement).offsetHeight + 28; + if (trueCellHeight > maxCellHeight) { + maxCellHeight = trueCellHeight; + } + } + } + return currentRowHeight - maxCellHeight === 1 ? currentRowHeight : maxCellHeight; + }; + + React.useEffect(() => { + const currentRowHeight = getCurrentRowHeight(); + const [scrollRef, rightRef] = props.siblings; + const scrollColumnsHeight = scrollRef.current?.getRowHeight() || 0; + const rightFixedColumnsHeight = rightRef.current?.getRowHeight() || 0; + const maxSiblingsHeight = Math.max(scrollColumnsHeight, rightFixedColumnsHeight); + if (maxSiblingsHeight > currentRowHeight) { + setRowHeight(maxSiblingsHeight); + } + }, [props.columnList, props.tableConfig, props.dataSource]); + + React.useImperativeHandle(ref, () => ({ + getRowHeight: getCurrentRowHeight, + getSubTableHeight: () => { + const rows = (containerRef.current?.children || []) as HTMLDivElement[]; + const start = props.tableConfig.configs.showHeader ? 1 : 0; + const subTableHeights: number[] = []; + for (let i = start; i < rows.length; i++) { + if (rows[i].className === 'jfe-drip-table-generator-workstation-table-row' + || rows[i].className === 'jfe-drip-table-generator-workstation-table-row stripe' + ) { + if (rows[i + 1]?.className === 'subtable') { + subTableHeights.push(rows[i + 1].offsetHeight); + } else { + subTableHeights.push(0); + } + } + } + return subTableHeights; + }, + })); + return ( +
0 || props.tableConfig.hasSubTable || props.tableConfig.configs.rowSelection, + })} + ref={containerRef} + style={{ width: props.tableConfig.hasSubTable ? leftMargins : void 0 }} + > +
+ {props.tableConfig.hasSubTable && ( +
+ )} + {props.tableConfig.configs.rowSelection && ( +
+ +
+ )} + {props.columnList.map(columnWrapper => ( + + ))} +
+ {props.previewDataSource.map((record, rowIndex) => { + const hasSubTable = tableConfigs[currentTableIndex + 1] && Object.keys(record.record || {}).includes(tableConfigs[currentTableIndex + 1]?.dataSourceKey); + const tableInfo: DripTableTableInformation = { + uuid: props.tableConfig?.tableId, + schema: { + ...props.tableConfig?.configs, + id: props.tableConfig.tableId ?? mockId(), + columns: props.tableConfig?.columns, + dataSourceKey: props.tableConfig?.dataSourceKey, + } as DripTableTableInformation['schema'], + dataSource: record?.[tableConfigs[currentTableIndex + 1]?.dataSourceKey || ''] as RecordType[] || [], + record: record.record, + }; + return ( + + {props.tableConfig.configs.rowHeader && ( +
+ )} +
+ {props.tableConfig.hasSubTable && ( +
+ {hasSubTable && } +
+ )} + {props.tableConfig.configs.rowSelection && ( +
+ { + props.renderSelection + ? ( + false} + /> + ) + : + } +
+ )} + +
+ {(props.tableConfig.hasSubTable && hasSubTable) + && ( +
+ +
+ )} + + ); + })} +
+ ); +} + +// 使用 forwardRef 包装 +const LeftFixedColumns = React.forwardRef(LeftFixedColumnsInner) as >, + ExtraOptions extends Partial = never>(props: LeftFixedColumnsProps, ref: React.ForwardedRef) => JSX.Element; + +export default LeftFixedColumns; diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/right-columns/index.less b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/right-columns/index.less new file mode 100644 index 000000000..9cd13088f --- /dev/null +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/right-columns/index.less @@ -0,0 +1,77 @@ +/** + * This file is part of the drip-table project. + * @link : https://drip-table.jd.com/ + * @author : helloqian12138 (johnhello12138@163.com) + * @modifier : helloqian12138 (johnhello12138@163.com) + * @copyright: Copyright (c) 2020 JD Network Technology Co., Ltd. + */ + +@import url("../../../../../styles/index.less"); + +@prefixCls: jfe-drip-table-generator-workstation-table; + +.@{prefixCls}-fixed-column { + position: sticky; + z-index: 3; + background: #ffffff; + height: max-content; + + &.right { + right: 0; + } + + &.bordered { + border-right: 1px solid rgb(196 196 196); + box-shadow: 0 0 4px -1px #ffffff, -2px 0 4px -2px rgb(0 0 0 / 85%); + } + + & > .@{prefixCls}-row { + display: flex; + width: 100%; + + &.stripe { + background-color: #efefef; + } + } + + & > .@{prefixCls}-header { + background: #dddddd; + font-weight: bold; + + &.sticky { + position: sticky; + top: 0; + z-index: 10; + } + + &.invisible { + .@{prefixCls}-header-item { + opacity: .7; + background: + linear-gradient( + 45deg, + var(--drip-table-background-color, @background-color) 0, + var(--drip-table-background-color, @background-color) 10%, + transparent 10%, + transparent 20%, + var(--drip-table-background-color, @background-color) 20%, + var(--drip-table-background-color, @background-color) 30%, + transparent 30%, + transparent 40%, + var(--drip-table-background-color, @background-color) 40%, + var(--drip-table-background-color, @background-color) 50%, + transparent 50%, + transparent 60%, + var(--drip-table-background-color, @background-color) 60%, + var(--drip-table-background-color, @background-color) 70%, + transparent 70%, + transparent 80%, + var(--drip-table-background-color, @background-color) 80%, + var(--drip-table-background-color, @background-color) 90%, + transparent 90%, + transparent 100% + ); + } + } + } +} diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/right-columns/index.tsx b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/right-columns/index.tsx new file mode 100644 index 000000000..578a38d35 --- /dev/null +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/right-columns/index.tsx @@ -0,0 +1,142 @@ +/** + * This file is part of the drip-table project. + * @link : https://drip-table.jd.com/ + * @author : helloqian12138 (johnhello12138@163.com) + * @modifier : helloqian12138 (johnhello12138@163.com) + * @copyright: Copyright (c) 2020 JD Network Technology Co., Ltd. + */ +import './index.less'; + +import classNames from 'classnames'; +import { DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, ExtractDripTableExtraOption } from 'drip-table'; +import React from 'react'; + +import { DTGTableConfig } from '@/context/table-configs'; +import { DripTableGeneratorProps } from '@/typing'; + +import ColumnHeader from '../column-header'; +import { LeftFixedColumnsHandler } from '../left-columns'; +import { ScrollableColumnsHandler } from '../scroll-columns'; +import TableSection from '../table-section'; + +export interface RightFixedColumnsProps< + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never +> extends DripTableGeneratorProps { + tableConfig: DTGTableConfig; + previewDataSource: ({ id: number; record: RecordType })[]; + containerWidth: number; + siblings: [React.RefObject, React.RefObject]; + columnList: { id: number; column: DTGTableConfig['columns'][number] }[]; + ref?: React.RefObject; + subTableHeights?: number[]; + rowHeaderHeights?: number[]; +} + +export interface RightFixedColumnsHandler { + getRowHeight: () => number; +} + +function RightFixedColumnsInner< + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never +>( + props: RightFixedColumnsProps, + ref: React.ForwardedRef, +) { + const rowRef = React.createRef(); + const [rowHeight, setRowHeight] = React.useState(void 0 as number | undefined); + + const getCurrentRowHeight = () => { + let maxCellHeight = 0; + const currentRowHeight = rowRef.current?.offsetHeight ?? 0; + for (const element of (rowRef.current?.children || []) as HTMLDivElement[]) { + if (element.children[0]) { + const trueCellHeight = (element.children[0] as HTMLDivElement).offsetHeight + 28; + if (trueCellHeight > maxCellHeight) { + maxCellHeight = trueCellHeight; + } + } + } + return currentRowHeight - maxCellHeight === 1 ? currentRowHeight : maxCellHeight; + }; + + React.useEffect(() => { + const currentRowHeight = getCurrentRowHeight(); + const [leftRef, scrollRef] = props.siblings; + const leftFixedColumnsHeight = leftRef.current?.getRowHeight() || 0; + const scrollColumnsHeight = scrollRef.current?.getRowHeight() || 0; + const maxSiblingsHeight = Math.max(scrollColumnsHeight, leftFixedColumnsHeight); + if (maxSiblingsHeight > currentRowHeight) { + setRowHeight(maxSiblingsHeight); + } + }, [props.columnList, props.tableConfig, props.dataSource]); + + React.useImperativeHandle(ref, () => ({ + getRowHeight: getCurrentRowHeight, + })); + return ( +
0 || props.tableConfig.hasSubTable || props.tableConfig.configs.rowSelection, + })} + > +
+ {props.columnList.map(columnWrapper => ( + + ))} +
+ {props.previewDataSource.map((record, rowIndex) => ( + + {props.tableConfig.configs.rowHeader && ( +
+ )} +
+ +
+ {(props.subTableHeights?.length || 0) > 0 && (props.subTableHeights?.[rowIndex] || 0) > 0 && ( +
+ )} + + ))} +
+ ); +} + +// 使用 forwardRef 包装 +const RightFixedColumns = React.forwardRef(RightFixedColumnsInner) as >, + ExtraOptions extends Partial = never>(props: RightFixedColumnsProps, ref: React.ForwardedRef) => JSX.Element; + +export default RightFixedColumns; diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/row/index.less b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/row/index.less index 8d0c463df..a76aa90bf 100644 --- a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/row/index.less +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/row/index.less @@ -71,6 +71,10 @@ min-width: 48px; justify-content: center; align-items: center; + + &.bordered { + min-width: 47px; + } } } diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/row/index.tsx b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/row/index.tsx index c3590f4aa..c8f93152d 100644 --- a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/row/index.tsx +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/row/index.tsx @@ -10,21 +10,21 @@ import './index.less'; import { PlusSquareOutlined } from '@ant-design/icons'; import { Checkbox } from 'antd'; import classNames from 'classnames'; -import { DripTableBuiltInColumnSchema, DripTableExtraOptions, DripTableProps } from 'drip-table'; +import { DripTableBuiltInColumnSchema, DripTableExtraOptions, DripTableProps, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, ExtractDripTableExtraOption } from 'drip-table'; import React from 'react'; import { filterArray, formatNumber } from '@/utils'; import { GeneratorContext } from '@/context'; import { DTGTableConfig } from '@/context/table-configs'; -import { DataSourceTypeAbbr, DripTableGeneratorProps } from '@/typing'; +import { DripTableGeneratorProps } from '@/typing'; import TableCell from '../cell'; import RowHeader from './row-header'; interface TableRowListProps< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, ->{ + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, +> { rowIndex: number; isLastRow?: boolean; scrollTarget: string; @@ -59,8 +59,8 @@ const VerticalAligns = { }; function TableRowList< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, >(props: TableRowListProps) { const { currentTableID, currentColumnID, currentHoverColumnID, previewDataSource } = React.useContext(GeneratorContext); const scrollableRow = React.useRef(null); @@ -135,14 +135,14 @@ ExtraOptions extends Partial = never, return ( - { props.tableConfig.configs.rowHeader && ( + {props.tableConfig.configs.rowHeader && ( - ) } + )}
{ @@ -150,44 +150,47 @@ ExtraOptions extends Partial = never, props.onClick?.('row-click', { record: props.record, recordIndex: props.rowIndex }); }} > - { props.tableConfig.hasSubTable && ( -
- { props.hasSubTable && } -
- ) } - { props.tableConfig.configs.rowSelection && ( -
- { - props.renderSelection - ? ( - false} - /> - ) - : - } -
- ) } - { leftFixedColumns.length > 0 - ? leftFixedColumns.map((columnWrapper, index) => - renderTableCell(columnWrapper.column as DripTableBuiltInColumnSchema, columnWrapper.id, { - showRightShadow: index === leftFixedColumns.length - 1, - isLastRow: props.isLastRow, - })) - : null } + {props.tableConfig.hasSubTable && ( +
+ {props.hasSubTable && } +
+ )} + {props.tableConfig.configs.rowSelection && ( +
+ { + props.renderSelection + ? ( + false} + /> + ) + : + } +
+ )} + {leftFixedColumns.length > 0 + ? ( +
+ {leftFixedColumns.map((columnWrapper, index) => + renderTableCell(columnWrapper.column as DripTableBuiltInColumnSchema, columnWrapper.id, { + isLastRow: props.isLastRow, + }))} +
+ ) + : null}
= never, onScroll={(e) => { if (props.scrollTarget === `__row_${props.rowIndex}`) { props.onScroll((e.target as HTMLDivElement).scrollLeft); } }} >
- { sortableColumns.map(columnWrapper => + {sortableColumns.map(columnWrapper => renderTableCell(columnWrapper.column as DripTableBuiltInColumnSchema, columnWrapper.id, { isLastRow: props.isLastRow, - })) } + }))}
- { rightFixedColumns.length > 0 + {rightFixedColumns.length > 0 ? rightFixedColumns.map((columnWrapper, index) => renderTableCell(columnWrapper.column as DripTableBuiltInColumnSchema, columnWrapper.id, { showLeftShadow: !index, isLastRow: props.isLastRow, })) - : null } + : null}
diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/row/row-header/index.tsx b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/row/row-header/index.tsx index 7b4e3b621..74b602676 100644 --- a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/row/row-header/index.tsx +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/row/row-header/index.tsx @@ -9,7 +9,7 @@ import { DownOutlined, PlusOutlined } from '@ant-design/icons'; import { Button, Input, Select } from 'antd'; import classNames from 'classnames'; -import { DripTableExtraOptions, DripTableSlotElementSchema } from 'drip-table'; +import { DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, DripTableSlotElementSchema, ExtractDripTableExtraOption } from 'drip-table'; import cloneDeep from 'lodash/cloneDeep'; import React from 'react'; @@ -17,10 +17,10 @@ import RichText from '@/components/RichText'; import { GeneratorContext } from '@/context'; import { DTGTableConfig, DTGTableConfigsContext, TableConfigsContext } from '@/context/table-configs'; import { getSchemaValue } from '@/layouts/utils'; -import { DataSourceTypeAbbr, DripTableGeneratorProps } from '@/typing'; +import { DripTableGeneratorProps } from '@/typing'; interface RowHeaderProps< - RecordType extends DataSourceTypeAbbr>, + RecordType extends DripTableRecordTypeWithSubtable>, ExtraOptions extends Partial = never, > { ext: DripTableGeneratorProps['ext']; @@ -29,8 +29,8 @@ interface RowHeaderProps< tableConfig: DTGTableConfig; } function RowHeader< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, >(props: RowHeaderProps) { const context = React.useContext(GeneratorContext); const tableConfigsContext = React.useContext(TableConfigsContext); @@ -43,7 +43,7 @@ ExtraOptions extends Partial = never, } if (config.type === 'text') { - return

{ config.text }

; + return

{config.text}

; } if (config.type === 'html') { @@ -53,14 +53,14 @@ ExtraOptions extends Partial = never, if (config.type === 'search') { return (
- { config.searchKeys && ( + {config.searchKeys && ( - ) } + )} = never, /> ); } - return { `自定义插槽组件渲染函数 tableProps.slots['${config.slot}'] 不存在` }; + return {`自定义插槽组件渲染函数 tableProps.slots['${config.slot}'] 不存在`}; } if (config.type === 'insert-button') { @@ -99,7 +99,7 @@ ExtraOptions extends Partial = never, icon={config.showIcon && } style={config.insertButtonStyle} > - { config.insertButtonText } + {config.insertButtonText} ); } @@ -107,7 +107,7 @@ ExtraOptions extends Partial = never, if (config.type === 'display-column-selector') { return ( ); @@ -133,11 +133,13 @@ ExtraOptions extends Partial = never, newColumns.splice(cellIndex, 1, currentCell); setCurrentCellIndex(-1); setCurrentCell(void 0); - const configs = cloneDeep({ ...props.tableConfig.configs, + const configs = cloneDeep({ + ...props.tableConfig.configs, rowHeader: { ...props.tableConfig.configs.rowHeader, elements: newColumns, - } }); + }, + }); setTableConfigs(configs, tableIndex); } } @@ -145,8 +147,8 @@ ExtraOptions extends Partial = never, return ( - { ({ setTableConfigs }) => ( -
+ {({ setTableConfigs }) => ( +
{ props.configs?.elements?.map((element, index) => (
= never, dropHeaderCell(element, index, setTableConfigs); }} key={index} - className={classNames( - 'jfe-drip-table-generator-workstation-editable-header-draggable-cell', { - 'jfe-drip-table-generator-workstation-editable-header-text-cell': element.type === 'text', - 'jfe-drip-table-generator-workstation-editable-header-spacer-cell': element.type === 'spacer', - }, - )} + className={classNames('jfe-drip-table-generator-workstation-editable-header-draggable-cell', { + 'jfe-drip-table-generator-workstation-editable-header-text-cell': element.type === 'text', + 'jfe-drip-table-generator-workstation-editable-header-spacer-cell': element.type === 'spacer', + })} style={{ width: Number(element.span) ? `${(Number(element.span) * 100) / 24}%` : void 0, ...element.style }} > - { renderColumnContent(element) } + {renderColumnContent(element)}
)) }
- ) } + )} ); diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/scroll-columns/index.less b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/scroll-columns/index.less new file mode 100644 index 000000000..30e06d94f --- /dev/null +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/scroll-columns/index.less @@ -0,0 +1,67 @@ +/** + * This file is part of the drip-table project. + * @link : https://drip-table.jd.com/ + * @author : helloqian12138 (johnhello12138@163.com) + * @modifier : helloqian12138 (johnhello12138@163.com) + * @copyright: Copyright (c) 2020 JD Network Technology Co., Ltd. + */ + +@import url("../../../../../styles/index.less"); + +@prefixCls: jfe-drip-table-generator-workstation-table; + +.@{prefixCls}-scrollable-columns { + width: max-content; + height: max-content; + z-index: 2; + + & > .@{prefixCls}-row { + display: flex; + width: 100%; + + &.stripe { + background-color: #efefef; + } + } + + & > .@{prefixCls}-header { + background: #dddddd; + font-weight: bold; + + &.sticky { + position: sticky; + top: 0; + z-index: 10; + } + + &.invisible { + .@{prefixCls}-header-item { + opacity: .7; + background: + linear-gradient( + 45deg, + var(--drip-table-background-color, @background-color) 0, + var(--drip-table-background-color, @background-color) 10%, + transparent 10%, + transparent 20%, + var(--drip-table-background-color, @background-color) 20%, + var(--drip-table-background-color, @background-color) 30%, + transparent 30%, + transparent 40%, + var(--drip-table-background-color, @background-color) 40%, + var(--drip-table-background-color, @background-color) 50%, + transparent 50%, + transparent 60%, + var(--drip-table-background-color, @background-color) 60%, + var(--drip-table-background-color, @background-color) 70%, + transparent 70%, + transparent 80%, + var(--drip-table-background-color, @background-color) 80%, + var(--drip-table-background-color, @background-color) 90%, + transparent 90%, + transparent 100% + ); + } + } + } +} diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/scroll-columns/index.tsx b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/scroll-columns/index.tsx new file mode 100644 index 000000000..b88009130 --- /dev/null +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/scroll-columns/index.tsx @@ -0,0 +1,162 @@ +/** + * This file is part of the drip-table project. + * @link : https://drip-table.jd.com/ + * @author : helloqian12138 (johnhello12138@163.com) + * @modifier : helloqian12138 (johnhello12138@163.com) + * @copyright: Copyright (c) 2020 JD Network Technology Co., Ltd. + */ +import './index.less'; + +import classNames from 'classnames'; +import { DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, ExtractDripTableExtraOption } from 'drip-table'; +import React from 'react'; + +import { DTGTableConfig } from '@/context/table-configs'; +import { DripTableGeneratorProps } from '@/typing'; + +import ColumnHeader from '../column-header'; +import { LeftFixedColumnsHandler } from '../left-columns'; +import { RightFixedColumnsHandler } from '../right-columns'; +import RowHeader from '../row/row-header'; +import TableSection from '../table-section'; + +export interface ScrollableColumnsProps< + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never +> extends DripTableGeneratorProps { + tableConfig: DTGTableConfig; + previewDataSource: ({ id: number; record: RecordType })[]; + containerWidth: number; + siblings: [React.RefObject, React.RefObject]; + columnList: { id: number; column: DTGTableConfig['columns'][number] }[]; + ref?: React.RefObject; + subTableHeights?: number[]; +} + +export interface ScrollableColumnsHandler { + getRowHeight: () => number; + getRowHeaderHeights: () => number[]; +} + +function ScrollableColumnsInner< + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never +>( + props: ScrollableColumnsProps, + ref: React.ForwardedRef, +) { + const rowRef = React.createRef(); + const containerRef = React.createRef(); + const [rowHeight, setRowHeight] = React.useState(void 0 as number | undefined); + + const getCurrentRowHeight = () => { + let maxCellHeight = 0; + const currentRowHeight = rowRef.current?.offsetHeight ?? 0; + for (const element of (rowRef.current?.children || []) as HTMLDivElement[]) { + if (element.children[0]) { + const trueCellHeight = (element.children[0] as HTMLDivElement).offsetHeight + 28; + if (trueCellHeight > maxCellHeight) { + maxCellHeight = trueCellHeight; + } + } + } + return currentRowHeight - maxCellHeight === 1 ? currentRowHeight : maxCellHeight; + }; + + React.useEffect(() => { + const currentRowHeight = getCurrentRowHeight(); + const [leftRef, rightRef] = props.siblings; + const leftFixedColumnsHeight = leftRef.current?.getRowHeight() || 0; + const rightFixedColumnsHeight = rightRef.current?.getRowHeight() || 0; + const maxSiblingsHeight = Math.max(rightFixedColumnsHeight, leftFixedColumnsHeight); + if (maxSiblingsHeight > currentRowHeight) { + setRowHeight(maxSiblingsHeight); + } + }, [props.columnList, props.tableConfig, props.dataSource]); + + React.useImperativeHandle(ref, () => ({ + getRowHeight: getCurrentRowHeight, + getRowHeaderHeights: () => { + const rows = (containerRef.current?.children || []) as HTMLDivElement[]; + const start = props.tableConfig.configs.showHeader ? 1 : 0; + const rowHeaderHeights: number[] = []; + for (let i = start; i < rows.length; i++) { + if (rows[i].className === 'jfe-drip-table-generator-workstation-table-row' + || rows[i].className === 'jfe-drip-table-generator-workstation-table-row stripe' + ) { + if (rows[i - 1]?.className === 'rowHeader') { + rowHeaderHeights.push(rows[i - 1].offsetHeight); + } else { + rowHeaderHeights.push(0); + } + } + } + return rowHeaderHeights; + }, + })); + return ( +
+
+ {props.columnList.map(columnWrapper => ( + + ))} +
+ {props.previewDataSource.map((record, rowIndex) => ( + + {props.tableConfig.configs.rowHeader && ( + + )} +
+ +
+ {(props.subTableHeights?.length || 0) > 0 && (props.subTableHeights?.[rowIndex] || 0) > 0 && ( +
+ )} + + ))} +
+ ); +} + +// 使用 forwardRef 包装 +const ScrollableColumns = React.forwardRef(ScrollableColumnsInner) as >, + ExtraOptions extends Partial = never>(props: ScrollableColumnsProps, ref: React.ForwardedRef) => JSX.Element; + +export default ScrollableColumns; diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/table-section/index.less b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/table-section/index.less new file mode 100644 index 000000000..2bc00172c --- /dev/null +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/table-section/index.less @@ -0,0 +1,80 @@ +/** + * This file is part of the drip-table project. + * @link : https://drip-table.jd.com/ + * @author : helloqian12138 (johnhello12138@163.com) + * @modifier : helloqian12138 (johnhello12138@163.com) + * @copyright: Copyright (c) 2020 JD Network Technology Co., Ltd. + */ + +@import url("../../../../../styles/index.less"); + +@prefixCls: jfe-drip-table-generator-workstation-table; + +.@{prefixCls}-tr-td { + min-width: 120px; + display: flex; + padding: 12px 8px; + border-left: 1px solid transparent; + word-break: break-word; + + &.cell { + box-sizing: border-box; + flex-shrink: 0; + border-bottom: 1px solid #efefef; + } + + &.small { + padding: 8px; + } + + &.middle { + padding: 12px 8px; + } + + &.large { + padding: 16px 12px; + } + + &.bordered { + border-right: 1px solid #efefef; + } + + &.hovered { + border-left: 1px dashed var(--drip-table-border-color, @border-color); + border-right: 1px dashed var(--drip-table-border-color, @border-color); + } + + &.last-row.hovered { + border-bottom: 1px dashed var(--drip-table-border-color, @border-color); + } + + &.checked { + border-left: 1px solid var(--drip-table-border-color, @border-color); + border-right: 1px solid var(--drip-table-border-color, @border-color); + } + + &.last-row.checked { + border-bottom: 1px solid var(--drip-table-border-color, @border-color); + } + + &.right-shadow { + box-shadow: 0 4px 4px -1px #ffffff, 2px 0 4px -2px rgb(0 0 0 / 85%); + margin-right: 4px; + } + + &.left-shadow { + box-shadow: 0 0 4px -1px #ffffff, -2px 0 4px -2px rgb(0 0 0 / 85%); + margin-left: 4px; + } + + &.operation-col { + width: 48px; + min-width: 48px; + justify-content: center; + align-items: center; + + &.bordered { + min-width: 47px; + } + } +} diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/table-section/index.tsx b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/table-section/index.tsx new file mode 100644 index 000000000..a867fa781 --- /dev/null +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/components/table-section/index.tsx @@ -0,0 +1,90 @@ +import './index.less'; + +import classNames from 'classnames'; +import { DripTableBuiltInColumnSchema, DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, ExtractDripTableExtraOption } from 'drip-table'; +import React from 'react'; + +import { formatNumber } from '@/utils'; +import { GeneratorContext } from '@/context'; +import { DTGTableConfig } from '@/context/table-configs'; +import { DripTableGeneratorProps } from '@/typing'; + +import TableCell from '../cell'; + +export interface TableSectionProps< + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, +> extends DripTableGeneratorProps { + tableConfig: DTGTableConfig; + record: { id: number; record: RecordType }; + rowIndex: number; + columnList: { id: number; column: DTGTableConfig['columns'][number] }[]; + containerWidth: number; + isLastRow: boolean; +} + +const VerticalAligns = { + top: 'flex-start', + middle: 'center', + bottom: 'flex-end', + stretch: 'stretch', +}; + +function TableSection< + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, +>(props: TableSectionProps) { + const { currentTableID, currentColumnID, currentHoverColumnID } = React.useContext(GeneratorContext); + const formatColumnWidth = (column: DripTableBuiltInColumnSchema) => { + if (typeof column.width === 'string' && column.width.endsWith('%')) { + const rawColumnWidth = (Number(column.width.slice(0, -1)) * props.containerWidth) / 100; + return `${rawColumnWidth}px`; + } + return formatNumber(column.width || 200); + }; + return ( + + {props.columnList.map((columnWrapper, colIndex) => ( +
+ +
+ ))} +
+ ); +} + +export default TableSection; diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/index.less b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/index.less index 279f0a524..b8b538228 100644 --- a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/index.less +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/index.less @@ -25,10 +25,10 @@ position: relative; outline: none; - &:hover { - background-color: #efefef; - border: 1px dashed var(--drip-table-border-color, @border-color); - } + // &:hover { + // background-color: #efefef; + // border: 1px dashed var(--drip-table-border-color, @border-color); + // } &.stripe { background-color: #efefef; diff --git a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/index.tsx b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/index.tsx index f17d49053..a20295c87 100644 --- a/packages/drip-table-generator/src/layouts/table-workstation/editable-table/index.tsx +++ b/packages/drip-table-generator/src/layouts/table-workstation/editable-table/index.tsx @@ -7,49 +7,50 @@ */ import './index.less'; -import { EyeInvisibleOutlined, EyeOutlined } from '@ant-design/icons'; -import { Button, Empty } from 'antd'; import classNames from 'classnames'; -import { DripTableExtraOptions, DripTableTableInformation } from 'drip-table'; +import { DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, DripTableTableInformation, ExtractDripTableExtraOption } from 'drip-table'; import React from 'react'; import { filterArray, mockId } from '@/utils'; -import { GeneratorContext } from '@/context'; import { DTGTableConfig, TableConfigsContext } from '@/context/table-configs'; -import { DataSourceTypeAbbr, DripTableGeneratorProps } from '@/typing'; +import { DripTableGeneratorProps } from '@/typing'; import PaginationComponent from '../components/pagination'; import TableContainer, { TableContainerHandler } from '../components/table-container'; -import ColumnHeaderList from './components/header-list'; -import TableRowList from './components/row'; +import AddColumnComponent from './components/add-column'; +import LeftFixedColumns, { LeftFixedColumnsHandler } from './components/left-columns'; +import RightFixedColumns, { RightFixedColumnsHandler } from './components/right-columns'; +import ScrollableColumns, { ScrollableColumnsHandler } from './components/scroll-columns'; export interface EditableTableProps< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, > extends DripTableGeneratorProps { index: number; tableConfig: DTGTableConfig; - dataSource: RecordType[]; originDataSource?: RecordType[]; parent?: DripTableTableInformation; } function EditableTable< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, >(props: EditableTableProps) { - const context = React.useContext(GeneratorContext); - const [checkedRecord, setCheckedRecord] = React.useState(void 0 as number | undefined); - const [previewRecord, setPreviewRecord] = React.useState(void 0 as number | undefined); - const [scrollLeft, setScrollLeft] = React.useState(0); - const [scrollTarget, setScrollTarget] = React.useState(''); + const context = React.useContext(TableConfigsContext); + const [previewRecord] = React.useState(void 0 as number | undefined); + const [subTableHeights, setSubTableHeights] = React.useState([] as number[]); + const [rowHeaderHeights, setRowHeaderHeights] = React.useState([] as number[]); const containerRef = React.useRef(null); + const leftColumnsRef = React.useRef(null); + const scrollColumnsRef = React.useRef(null); + const rightColumnsRef = React.useRef(null); + const tableHeight = React.useMemo(() => { if (props.tableConfig.configs.scroll?.y && typeof props.tableConfig.configs.scroll?.y !== 'boolean') { return props.tableConfig.configs.scroll?.y; } return '100%'; - }, []); + }, [props.tableConfig.configs.scroll?.y]); const tableWidth = React.useMemo(() => { const defaultWidth = props.tableConfig.columns.length * 200; return containerRef.current?.getContainerWidth?.() || defaultWidth; @@ -67,183 +68,122 @@ ExtraOptions extends Partial = never, return props.dataSource.map((rec, idx) => ({ id: idx, record: rec })); }, [props.dataSource, props.tableConfig.configs.pagination, previewRecord]); + const previewDataSource = typeof previewRecord === 'number' ? [dataSourceToUse[previewRecord]] : dataSourceToUse; + const paginationInHeader = props.tableConfig.configs.pagination && props.tableConfig.configs.pagination.position?.startsWith('top'); + const paginationInFooter = props.tableConfig.configs.pagination && props.tableConfig.configs.pagination.position?.startsWith('bottom'); + const subTableInfo = { + uuid: props.tableConfig?.tableId, + schema: { + ...props.tableConfig?.configs, + id: props.tableConfig.tableId ?? mockId(), + columns: props.tableConfig?.columns, + dataSourceKey: props.tableConfig?.dataSourceKey, + } as DripTableTableInformation['schema'], + parent: props.parent, + dataSource: dataSourceToUse.map(item => item.record), + }; + const columnList = React.useMemo(() => props.tableConfig.columns.map((item, index) => ({ id: index, column: item })), [props.tableConfig.columns]); + const sortableColumns = filterArray(columnList, item => !item.column.fixed); + let leftFixedColumns = filterArray(columnList, item => item.column.fixed === 'left'); + let rightFixedColumns = filterArray(columnList, item => item.column.fixed === 'right'); + if (sortableColumns.length > 0) { + leftFixedColumns = filterArray(columnList, item => item.column.fixed === 'left' || (item.column.fixed && item.id < sortableColumns[0].id)); + rightFixedColumns = filterArray(columnList, item => item.column.fixed === 'right' || (item.column.fixed && item.id > sortableColumns[0].id)); + } + + React.useEffect(() => { + setTimeout(() => { + const leftHeights = leftColumnsRef.current?.getSubTableHeight() ?? []; + setSubTableHeights(leftHeights); + }, 200); + }, [props.dataSource, props.schema, props.tableConfig, context.tableConfigs]); + + React.useEffect(() => { + setTimeout(() => { + const rowHeights = scrollColumnsRef.current?.getRowHeaderHeights() ?? []; + setRowHeaderHeights(rowHeights); + }, 200); + }, [props.dataSource, props.schema, props.tableConfig, context.tableConfigs]); + return ( - { ({ tableConfigs, setTableColumns }) => { - const previewDataSource = typeof previewRecord === 'number' ? [dataSourceToUse[previewRecord]] : dataSourceToUse; - const paginationInHeader = props.tableConfig.configs.pagination && props.tableConfig.configs.pagination.position?.startsWith('top'); - const paginationInFooter = props.tableConfig.configs.pagination && props.tableConfig.configs.pagination.position?.startsWith('bottom'); - const subTableInfo = { - uuid: props.tableConfig?.tableId, - schema: { - ...props.tableConfig?.configs, - id: props.tableConfig.tableId ?? mockId(), - columns: props.tableConfig?.columns, - dataSourceKey: props.tableConfig?.dataSourceKey, - } as DripTableTableInformation['schema'], - parent: props.parent, - dataSource: dataSourceToUse.map(item => item.record), - }; - return ( - - { props.parent?.record && (props.subtableTitle?.(props.parent.record, props.index || 0, subTableInfo) || '') } - { props.parent?.record && props.tableConfig.configs.pagination && paginationInHeader - ? ( - - ) - : null } + {({ tableConfigs, setTableColumns }) => ( + + {props.parent?.record && (props.subtableTitle?.(props.parent.record, props.index || 0, subTableInfo) || '')} + {props.parent?.record && props.tableConfig.configs.pagination && paginationInHeader + ? ( + + ) + : null} +
- { props.tableConfig.configs.sticky - ? ( - setTableColumns([...newColumns], props.index)} - onScroll={(left) => { setScrollLeft(left); }} - onClick={props.onClick} - onColumnAdded={props.onColumnAdded} - renderHeaderCellFilter={props.renderHeaderCellFilter} - containerWidth={tableWidth} - /> - ) - : null } -
- { !props.tableConfig.configs.sticky && ( - setTableColumns([...newColumns], props.index)} - onScroll={(left) => { setScrollLeft(left); }} - onClick={props.onClick} - onColumnAdded={props.onColumnAdded} - renderHeaderCellFilter={props.renderHeaderCellFilter} - containerWidth={tableWidth} - /> - ) } - { previewDataSource.map((wrapRecord, rowIndex) => { - const hasSubTable = tableConfigs[props.index + 1] && Object.keys(wrapRecord.record || {}).includes(tableConfigs[props.index + 1]?.dataSourceKey); - const tableInfo: DripTableTableInformation = { - uuid: props.tableConfig?.tableId, - schema: { - ...props.tableConfig?.configs, - id: props.tableConfig.tableId ?? mockId(), - columns: props.tableConfig?.columns, - dataSourceKey: props.tableConfig?.dataSourceKey, - } as DripTableTableInformation['schema'], - dataSource: wrapRecord?.[tableConfigs[props.index + 1]?.dataSourceKey || ''] as RecordType[] || [], - record: wrapRecord.record, - }; - return ( -
{ e.stopPropagation(); setScrollTarget(`__row_${rowIndex}`); }} - onMouseLeave={(e) => { e.stopPropagation(); setScrollTarget(''); }} - onClick={(e) => { - e.stopPropagation(); - if (props.generatorRowSelectable === false) { return; } - setCheckedRecord(checkedRecord === wrapRecord.id ? void 0 : wrapRecord.id); - }} - > - { checkedRecord === wrapRecord.id && props.tableConfig.tableId === context.currentTableID && ( -
-
- ) } - { setScrollLeft(left); }} - onClick={props.onClick} - onColumnItemChanged={props.onColumnItemChanged} - containerWidth={tableWidth} - schemaFunctionPreprocessor={props.schemaFunctionPreprocessor} - /> - { (props.tableConfig.hasSubTable && hasSubTable) - && ( -
- -
- ) } -
- ); - }) } - { previewDataSource.length <= 0 && (props.emptyText ? props.emptyText?.(subTableInfo) : ) } -
+ + {...props} + ref={leftColumnsRef} + tableConfig={props.tableConfig} + columnList={leftFixedColumns} + previewDataSource={previewDataSource as ({ id: number; record: RecordType })[]} + containerWidth={tableWidth} + rowHeaderHeights={rowHeaderHeights} + siblings={[scrollColumnsRef, rightColumnsRef]} + /> + + {...props} + ref={scrollColumnsRef} + tableConfig={props.tableConfig} + columnList={sortableColumns} + previewDataSource={previewDataSource} + containerWidth={tableWidth} + subTableHeights={subTableHeights} + siblings={[leftColumnsRef, rightColumnsRef]} + /> + + {...props} + ref={rightColumnsRef} + tableConfig={props.tableConfig} + columnList={rightFixedColumns} + previewDataSource={previewDataSource} + containerWidth={tableWidth} + subTableHeights={subTableHeights} + rowHeaderHeights={rowHeaderHeights} + siblings={[leftColumnsRef, scrollColumnsRef]} + />
- { props.parent?.record && props.tableConfig.configs.pagination && paginationInFooter - ? ( - - ) - : null } - { props.parent?.record && (props.subtableFooter?.(props.parent.record, props.index || 0, subTableInfo) || '') } - - ); - } } + +
+ {props.parent?.record && props.tableConfig.configs.pagination && paginationInFooter + ? ( + + ) + : null} + {props.parent?.record && (props.subtableFooter?.(props.parent.record, props.index || 0, subTableInfo) || '')} +
+ )}
); } diff --git a/packages/drip-table-generator/src/layouts/table-workstation/index.tsx b/packages/drip-table-generator/src/layouts/table-workstation/index.tsx index d8d3ad58d..7d09e6357 100644 --- a/packages/drip-table-generator/src/layouts/table-workstation/index.tsx +++ b/packages/drip-table-generator/src/layouts/table-workstation/index.tsx @@ -8,12 +8,12 @@ import './index.less'; import classNames from 'classnames'; -import { DripTableExtraOptions } from 'drip-table'; +import { DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, ExtractDripTableExtraOption } from 'drip-table'; import React from 'react'; import { GeneratorContext } from '@/context'; import { TableConfigsContext } from '@/context/table-configs'; -import { DataSourceTypeAbbr, DripTableGeneratorProps } from '@/typing'; +import { DripTableGeneratorProps } from '@/typing'; import EditableTableFooter from './editable-footer'; import EditableTableHeader from './editable-header'; @@ -21,14 +21,14 @@ import EditableTable from './editable-table'; import PreviewTable from './table-preview'; function TableWorkStation< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, >(props: DripTableGeneratorProps) { const { mode, previewDataSource } = React.useContext(GeneratorContext); const { tableConfigs } = React.useContext(TableConfigsContext); return (
- { mode === 'edit' + {mode === 'edit' ? ( = never, renderPagination={props.renderPagination} onPageChange={props.onPageChange} /> - { tableConfigs.length >= 0 && ( - - ) } + {tableConfigs.length >= 0 && ( + + )} = never, /> ) - : } + : }
); } diff --git a/packages/drip-table-generator/src/layouts/table-workstation/table-preview/index.tsx b/packages/drip-table-generator/src/layouts/table-workstation/table-preview/index.tsx index 77fd4d39b..0a569076b 100644 --- a/packages/drip-table-generator/src/layouts/table-workstation/table-preview/index.tsx +++ b/packages/drip-table-generator/src/layouts/table-workstation/table-preview/index.tsx @@ -7,17 +7,17 @@ */ import './index.less'; -import DripTable, { DripTableExtraOptions } from 'drip-table'; +import DripTable, { DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, ExtractDripTableExtraOption } from 'drip-table'; import React from 'react'; import { filterAttributes } from '@/utils'; import { GeneratorContext } from '@/context'; import { TableConfigsContext } from '@/context/table-configs'; import { getSchemaValue } from '@/layouts/utils'; -import { DataSourceTypeAbbr, DripTableGeneratorProps } from '@/typing'; +import { DripTableGeneratorProps } from '@/typing'; function PreviewTable< - RecordType extends DataSourceTypeAbbr>, + RecordType extends DripTableRecordTypeWithSubtable>, ExtraOptions extends Partial = never, >(props: DripTableGeneratorProps & { visible: boolean }) { const context = React.useContext(GeneratorContext); diff --git a/packages/drip-table-generator/src/layouts/toolbar/components/datasource/index.tsx b/packages/drip-table-generator/src/layouts/toolbar/components/datasource/index.tsx index 767429188..4271b080e 100644 --- a/packages/drip-table-generator/src/layouts/toolbar/components/datasource/index.tsx +++ b/packages/drip-table-generator/src/layouts/toolbar/components/datasource/index.tsx @@ -6,21 +6,21 @@ * @copyright: Copyright (c) 2020 JD Network Technology Co., Ltd. */ import { Alert } from 'antd'; -import { DripTableExtraOptions } from 'drip-table'; +import { DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, ExtractDripTableExtraOption } from 'drip-table'; import React from 'react'; import MonacoEditor from 'react-monaco-editor'; import { GeneratorContext } from '@/context'; -import { DataSourceTypeAbbr, DripTableGeneratorProps } from '@/typing'; +import { DripTableGeneratorProps } from '@/typing'; export type DataSourceHandler = { formatDataSource: () => void; } -interface DataSourceEditorProps < -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, ->{ +interface DataSourceEditorProps< + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, +> { width?: number; height?: number; onDataSourceChange: DripTableGeneratorProps['onDataSourceChange']; @@ -28,8 +28,8 @@ ExtraOptions extends Partial = never, } function DataSourceEditor< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, >(props: DataSourceEditorProps, ref: React.ForwardedRef) { const { previewDataSource } = React.useContext(GeneratorContext); const [codeErrorMessage, setCodeErrorMessage] = React.useState(''); @@ -50,7 +50,7 @@ ExtraOptions extends Partial = never, return ( - { ({ setState }) => ( + {({ setState }) => (
= never, } }} /> - { codeErrorMessage && } + {codeErrorMessage && }
- ) } + )}
); diff --git a/packages/drip-table-generator/src/layouts/toolbar/components/templates-manager/index.tsx b/packages/drip-table-generator/src/layouts/toolbar/components/templates-manager/index.tsx index 45d993f71..764386bbf 100644 --- a/packages/drip-table-generator/src/layouts/toolbar/components/templates-manager/index.tsx +++ b/packages/drip-table-generator/src/layouts/toolbar/components/templates-manager/index.tsx @@ -11,7 +11,7 @@ import './index.less'; import { CheckOutlined, ExclamationCircleFilled, MinusCircleOutlined, PlusCircleOutlined } from '@ant-design/icons'; import { AutoComplete, Button, Col, Image, Input, Modal, Row, Select } from 'antd'; import classNames from 'classnames'; -import { DripTableExtraOptions, DripTableSchema } from 'drip-table'; +import { DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, DripTableSchema, ExtractDripTableExtraOption } from 'drip-table'; import React from 'react'; import { filterAttributes, mockId } from '@/utils'; @@ -20,13 +20,13 @@ import { GeneratorContext } from '@/context'; import { DTGTableConfig, TableConfigsContext } from '@/context/table-configs'; import { defaultComponentIcon } from '@/layouts/table-workstation/editable-table/components/components-selector/configs'; import { generateTableConfigsBySchema, getComponentsConfigs } from '@/layouts/utils'; -import { DataSourceTypeAbbr, DripTableComponentAttrConfig, DripTableGeneratorProps } from '@/typing'; +import { DripTableComponentAttrConfig, DripTableGeneratorProps } from '@/typing'; import { DTGBuiltInTemplates } from '../../templates'; export interface TemplatesManagerProps< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, > { customComponentPanel: DripTableGeneratorProps['customComponentPanel']; mockDataSource: DripTableGeneratorProps['mockDataSource']; @@ -77,8 +77,8 @@ const getColumnSchemaByComponent = (component: DripTableComponentAttrConfig, tit }; function TemplatesManager< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, >(props: TemplatesManagerProps) { const { previewDataSource } = React.useContext(GeneratorContext); const [currentTemplate, setCurrentTemplate] = React.useState(''); @@ -144,9 +144,9 @@ ExtraOptions extends Partial = never, return (
- { currentStep === 0 && ( + {currentStep === 0 && (
- { templates.map((iTemplate, key) => ( + {templates.map((iTemplate, key) => (
= never, setSchemaToAdd(iTemplate.schema as DripTableSchema); }} > - { iTemplate.key === currentTemplate && ( -
- -
- ) } + {iTemplate.key === currentTemplate && ( +
+ +
+ )}
-
{ iTemplate.label }
+
{iTemplate.label}
- )) } + ))}
- ) } - { currentStep === 1 && ( + )} + {currentStep === 1 && (
序号 @@ -175,9 +175,9 @@ ExtraOptions extends Partial = never, 字段选择 操作 - { schemaToAdd?.columns.map((iColumn, key) => ( + {schemaToAdd?.columns.map((iColumn, key) => ( - { key + 1 } + {key + 1} updateColumnTitle(e.target.value, key)} /> @@ -193,12 +193,12 @@ ExtraOptions extends Partial = never, } }} > - { components.map((component, componentKey) => ( + {components.map((component, componentKey) => ( - { component.title } + {component.title} - )) } + ))} @@ -228,8 +228,8 @@ ExtraOptions extends Partial = never, /> - )) } - { (schemaToAdd && (schemaToAdd?.columns?.length || 0) <= 0) && ( + ))} + {(schemaToAdd && (schemaToAdd?.columns?.length || 0) <= 0) && ( - ) } + )}
- ) } - { currentTemplate && ( + )} + {currentTemplate && (
- { currentStep === 0 && } - { currentStep === 1 && ( - - ) } - { currentStep === 1 && ( - - { ({ tableConfigs, updateTableConfigs }) => ( - } + {currentStep === 1 && ( + + )} + {currentStep === 1 && ( + + {({ tableConfigs, updateTableConfigs }) => ( + - ) } - - ) } + }} + > + 确认设置 + + )} + + )}
- ) } + )}
); } diff --git a/packages/drip-table-generator/src/layouts/toolbar/index.tsx b/packages/drip-table-generator/src/layouts/toolbar/index.tsx index 184fb5cb2..227ca866f 100644 --- a/packages/drip-table-generator/src/layouts/toolbar/index.tsx +++ b/packages/drip-table-generator/src/layouts/toolbar/index.tsx @@ -9,13 +9,13 @@ import './index.less'; import { ArrowLeftOutlined, CloseOutlined, SaveOutlined } from '@ant-design/icons'; import { Button, message, Tooltip } from 'antd'; -import { DripTableColumnSchema, DripTableExtraOptions } from 'drip-table'; +import { DripTableColumnSchema, DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, ExtractDripTableExtraOption } from 'drip-table'; import React from 'react'; import { GeneratorContext } from '@/context'; import { DTGTableConfig, TableConfigsContext } from '@/context/table-configs'; import { getSchemaValue } from '@/layouts/utils'; -import { DataSourceTypeAbbr, DripTableGeneratorProps } from '@/typing'; +import { DripTableGeneratorProps } from '@/typing'; import DataSourceEditor from './components/datasource'; import DropDownButton, { DropDownButtonProps } from './components/dropdown-button'; @@ -62,7 +62,7 @@ function ModeSwitch(props: { style?: React.CSSProperties; disabled?: boolean }) }; return ( - { ({ mode, setState }) => ( + {({ mode, setState }) => ( - ) } + )} ); } function Toolbar< -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, >(props: DripTableGeneratorProps) { const { drawerType, setState } = React.useContext(GeneratorContext); const [operateMenu, setOperateMenu] = React.useState(void 0 as string | undefined); @@ -101,7 +101,7 @@ ExtraOptions extends Partial = never, return ( - { ({ tableConfigs, updateTableConfigs }) => ( + {({ tableConfigs, updateTableConfigs }) => (
= never, if (operateMenu) { setOperateMenu(void 0); } }} > - { props.save && props.savePosition !== 'right' && !operateMenu && ( + {props.save && props.savePosition !== 'right' && !operateMenu && (
- ) } + )}
); } diff --git a/packages/drip-table-generator/src/layouts/utils.ts b/packages/drip-table-generator/src/layouts/utils.ts index 6f0aacb5d..7fbb38735 100644 --- a/packages/drip-table-generator/src/layouts/utils.ts +++ b/packages/drip-table-generator/src/layouts/utils.ts @@ -6,7 +6,7 @@ * @copyright: Copyright (c) 2020 JD Network Technology Co., Ltd. */ -import { DripTableBuiltInColumnSchema, DripTableExtraOptions, DripTableSchema, ExtractDripTableColumnSchema, ExtractDripTableExtraOption } from 'drip-table'; +import { DripTableBuiltInColumnSchema, DripTableExtraOptions, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, DripTableSchema, ExtractDripTableColumnSchema, ExtractDripTableExtraOption } from 'drip-table'; import cloneDeep from 'lodash/cloneDeep'; import { filterAttributes, mockId } from '@/utils'; @@ -14,10 +14,10 @@ import { DripTableGeneratorContext } from '@/context'; import { DTGTableConfig } from '@/context/table-configs'; import tableComponents from '@/table-components'; -import { DataSourceTypeAbbr, DripTableComponentAttrConfig, DripTableGeneratorProps, DTGComponentPropertySchema } from '../typing'; +import { DripTableComponentAttrConfig, DripTableGeneratorProps, DTGComponentPropertySchema } from '../typing'; export const getGroups = < - RecordType extends DataSourceTypeAbbr>, + RecordType extends DripTableRecordTypeWithSubtable>, ExtraOptions extends Partial = never, >(customComponentPanel?: DripTableGeneratorProps['customComponentPanel']) => { let groups = [ @@ -38,7 +38,7 @@ export const getGroups = < }; export const getComponentsConfigs = < - RecordType extends DataSourceTypeAbbr>, + RecordType extends DripTableRecordTypeWithSubtable>, ExtraOptions extends Partial = never, >( groupName?: string, @@ -59,7 +59,7 @@ export const getComponentsConfigs = < }; export const getColumnItemConfigs = < -RecordType extends DataSourceTypeAbbr>, +RecordType extends DripTableRecordTypeWithSubtable>, ExtraOptions extends Partial = never, >(componentType: string, options: { componentsConfigs: DripTableComponentAttrConfig[]; diff --git a/packages/drip-table-generator/src/typing.ts b/packages/drip-table-generator/src/typing.ts index 16f816b44..d8e7bfb7e 100644 --- a/packages/drip-table-generator/src/typing.ts +++ b/packages/drip-table-generator/src/typing.ts @@ -1,4 +1,4 @@ -import { DripTableColumnSchema, DripTableExtraOptions, DripTableProps, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, DripTableSchema } from 'drip-table'; +import { DripTableColumnSchema, DripTableExtraOptions, DripTableProps, DripTableRecordTypeBase, DripTableRecordTypeWithSubtable, DripTableSchema, ExtractDripTableExtraOption } from 'drip-table'; import React, { CSSProperties, ReactNode } from 'react'; import { CustomComponentProps } from './components/CustomForm/components'; @@ -134,7 +134,7 @@ export interface DripTableGeneratorPanel { } export interface DTGCustomThemeOptions< -RecordType extends DataSourceTypeAbbr>, +RecordType extends DripTableRecordTypeWithSubtable>, ExtraOptions extends Partial = never, > { /** @@ -166,11 +166,14 @@ ExtraOptions extends Partial = never, export type NonColumnsPartialDTSchemaTypeAbbr = never> = Partial>, 'columns'>> -export type DataSourceTypeAbbr = DripTableRecordTypeWithSubtable; export interface DripTableGeneratorProps< - RecordType extends DataSourceTypeAbbr>, + RecordType extends DripTableRecordTypeWithSubtable>, ExtraOptions extends Partial = never, -> extends DripTableProps { +> extends Omit, 'onDataSourceChange'> { + /** + * 数据源 + */ + dataSource: RecordType[]; /** * 是否允许列拖拽 */ @@ -278,7 +281,7 @@ export interface DripTableGeneratorProps< preview?: boolean; onExportSchema?: (schema: DripTableSchema) => void; onSchemaChange?: (schema: DripTableSchema) => void; - onDataSourceChange?: (dataSource: DripTableProps['dataSource']) => void; + onDataSourceChange?: (data: RecordType[]) => void; onColumnAdded?: (column: DripTableSchema['columns'][number], schema: DripTableSchema, columnIndex: number) => void; onClose?: (schema?: DripTableSchema) => void; onSave?: (schema: DripTableSchema) => void; diff --git a/packages/drip-table-generator/src/wrapper/index.tsx b/packages/drip-table-generator/src/wrapper/index.tsx index 5aaf6fce3..60466318b 100644 --- a/packages/drip-table-generator/src/wrapper/index.tsx +++ b/packages/drip-table-generator/src/wrapper/index.tsx @@ -18,7 +18,7 @@ import { DTGTableConfig, DTGTableConfigsContext, TableConfigsContext } from '@/c import GeneratorLayout from '@/layouts'; import { generateTableConfigsBySchema, getSchemaValue } from '@/layouts/utils'; -import { DataSourceTypeAbbr, DripTableGeneratorProps } from '../typing'; +import { DripTableGeneratorProps } from '../typing'; export type GeneratorWrapperHandler = { getState: () => void; @@ -34,17 +34,20 @@ export type GeneratorWrapperHandler = { } const generateStates = < -RecordType extends DataSourceTypeAbbr>, -ExtraOptions extends Partial = never, ->(props: DripTableGeneratorProps): DripTableGeneratorStates => ({ - currentTableID: props.checkedTableId, - currentColumnID: props.checkedColumnId, + RecordType extends DripTableRecordTypeWithSubtable>, + ExtraOptions extends Partial = never, +>(props: DripTableGeneratorProps): DripTableGeneratorStates => { + const { checkedTableId, checkedColumnId } = props; + return { + currentTableID: checkedTableId, + currentColumnID: checkedColumnId, previewDataSource: [...props.dataSource || []], mode: props.defaultMode ?? 'edit', - }); + }; +}; const DripTableGenerator = React.forwardRef(< - RecordType extends DataSourceTypeAbbr>, + RecordType extends DripTableRecordTypeWithSubtable>, ExtraOptions extends Partial = never, >(props: DripTableGeneratorProps, ref: React.ForwardedRef) => { const [generatorStates, setGeneratorStates] = React.useState(generateStates(props)); @@ -151,7 +154,6 @@ const DripTableGenerator = React.forwardRef(< }) as < RecordType extends DripTableRecordTypeWithSubtable>, ExtraOptions extends Partial = never, -> (props: React.PropsWithoutRef> & React.RefAttributes) => -(React.ReactElement | null); +> (props: React.PropsWithoutRef> & React.RefAttributes) => (React.ReactElement | null); export default DripTableGenerator;