diff --git a/packages/core/client/src/collection-manager/CollectionField.tsx b/packages/core/client/src/collection-manager/CollectionField.tsx index 044ffc4e6..ca5d8f9a1 100644 --- a/packages/core/client/src/collection-manager/CollectionField.tsx +++ b/packages/core/client/src/collection-manager/CollectionField.tsx @@ -5,6 +5,7 @@ import React, { useEffect } from 'react'; import { useCompile, useComponent, useFormBlockContext } from '..'; import { CollectionFieldProvider } from './CollectionFieldProvider'; import { useCollectionField } from './hooks'; +import { concat } from 'lodash'; // TODO: 初步适配 const InternalField: React.FC = (props) => { @@ -38,8 +39,9 @@ const InternalField: React.FC = (props) => { setFieldProps('title', uiSchema.title); setFieldProps('description', uiSchema.description); setFieldProps('initialValue', uiSchema.default); - if (!field.validator && uiSchema['x-validator']) { - field.validator = uiSchema['x-validator']; + if (!field.validator && (uiSchema['x-validator'] || fieldSchema['x-validator'])) { + const concatSchema = concat([], uiSchema['x-validator'] || [], fieldSchema['x-validator'] || []) + field.validator = concatSchema; } if (fieldSchema['x-disabled'] === true) { field.disabled = true; diff --git a/packages/core/client/src/collection-manager/interfaces/input.ts b/packages/core/client/src/collection-manager/interfaces/input.ts index 0f973f1de..23aa2ffe9 100644 --- a/packages/core/client/src/collection-manager/interfaces/input.ts +++ b/packages/core/client/src/collection-manager/interfaces/input.ts @@ -1,6 +1,7 @@ import { ISchema } from '@formily/react'; import { defaultProps, operators } from './properties'; import { IField } from './types'; +import { i18n } from '../../i18n'; export const input: IField = { name: 'input', @@ -29,4 +30,110 @@ export const input: IField = { schema['x-component-props']['ellipsis'] = true; } }, + validateSchema(fieldSchema) { + return { + max: { + type: 'number', + title: '{{ t("Max length") }}', + minimum: 0, + 'x-decorator': 'FormItem', + 'x-component': 'InputNumber', + 'x-component-props': { + precision: 0 + }, + 'x-reactions': `{{(field) => { + const targetValue = field.query('.min').value(); + field.selfErrors = + !!targetValue && !!field.value && targetValue > field.value ? '${i18n.t('Max length must greater than min length')}' : '' + }}}`, + }, + min: { + type: 'number', + title: '{{ t("Min length") }}', + minimum: 0, + 'x-decorator': 'FormItem', + 'x-component': 'InputNumber', + 'x-component-props': { + precision: 0 + }, + 'x-reactions': { + dependencies: ['.max'], + fulfill: { + state: { + selfErrors: `{{!!$deps[0] && !!$self.value && $deps[0] < $self.value ? '${i18n.t('Min length must less than max length')}' : ''}}`, + }, + }, + }, + }, + len: { + type: 'number', + title: '{{ t("Length") }}', + minimum: 0, + 'x-decorator': 'FormItem', + 'x-component': 'InputNumber', + 'x-component-props': { + precision: 0 + }, + }, + format: { + type: 'string', + title: '{{ t("Format") }}', + 'x-decorator': 'FormItem', + 'x-component': 'Select', + 'x-component-props': { + allowClear: true, + }, + enum: [{ + label: '{{ t("url") }}', + value: 'url', + }, { + label: '{{ t("email") }}', + value: 'email', + }, { + label: '{{ t("ipv6") }}', + value: 'ipv6', + }, { + label: '{{ t("ipv4") }}', + value: 'ipv4', + }, { + label: '{{ t("number") }}', + value: 'number', + }, { + label: '{{ t("integer") }}', + value: 'integer', + }, { + label: '{{ t("idcard") }}', + value: 'idcard', + }, { + label: '{{ t("qq") }}', + value: 'qq', + }, { + label: '{{ t("phone") }}', + value: 'phone', + }, { + label: '{{ t("money") }}', + value: 'money', + }, { + label: '{{ t("zh") }}', + value: 'zh', + }, { + label: '{{ t("date") }}', + value: 'date', + }, { + label: '{{ t("zip") }}', + value: 'zip', + }] + }, + pattern: { + type: 'string', + title: '{{ t("Regular expression") }}', + 'x-decorator': 'FormItem', + 'x-component': 'Input', + 'x-component-props': { + prefix: '/', + suffix: '/', + } + }, + }; + } }; diff --git a/packages/core/client/src/collection-manager/interfaces/integer.ts b/packages/core/client/src/collection-manager/interfaces/integer.ts index b9c9533fe..074df86a7 100644 --- a/packages/core/client/src/collection-manager/interfaces/integer.ts +++ b/packages/core/client/src/collection-manager/interfaces/integer.ts @@ -1,5 +1,13 @@ import { defaultProps, operators } from './properties'; import { IField } from './types'; +import { i18n } from '../../i18n'; +import { registerValidateFormats } from '@formily/core'; +import { ISchema } from '@formily/react'; + +registerValidateFormats({ + odd: /^-?\d*[13579]$/, + even: /^-?\d*[02468]$/ +}); export const integer: IField = { name: 'integer', @@ -28,4 +36,65 @@ export const integer: IField = { filterable: { operators: operators.number, }, + validateSchema(fieldSchema) { + return { + maximum: { + type: 'number', + title: '{{ t("Maximum") }}', + 'x-decorator': 'FormItem', + 'x-component': 'InputNumber', + 'x-component-props': { + precision: 0 + }, + 'x-reactions': `{{(field) => { + const targetValue = field.query('.minimum').value(); + field.selfErrors = + !!targetValue && !!field.value && targetValue > field.value ? '${i18n.t('Maximum must greater than minimum')}' : '' + }}}`, + }, + minimum: { + type: 'number', + title: '{{ t("Minimum") }}', + 'x-decorator': 'FormItem', + 'x-component': 'InputNumber', + 'x-component-props': { + precision: 0 + }, + 'x-reactions': { + dependencies: ['.maximum'], + fulfill: { + state: { + selfErrors: `{{!!$deps[0] && !!$self.value && $deps[0] < $self.value ? '${i18n.t('Minimum must less than maximum')}' : ''}}`, + }, + }, + }, + }, + format: { + type: 'string', + title: '{{ t("Format") }}', + 'x-decorator': 'FormItem', + 'x-component': 'Select', + 'x-component-props': { + allowClear: true, + }, + enum: [{ + label: '{{ t("Odd") }}', + value: 'odd', + }, { + label: '{{ t("Even") }}', + value: 'even', + }] + }, + pattern: { + type: 'string', + title: '{{ t("Regular expression") }}', + 'x-decorator': 'FormItem', + 'x-component': 'Input', + 'x-component-props': { + prefix: '/', + suffix: '/', + } + }, + }; + } }; diff --git a/packages/core/client/src/collection-manager/interfaces/markdown.ts b/packages/core/client/src/collection-manager/interfaces/markdown.ts index 687987d28..0495c76b4 100644 --- a/packages/core/client/src/collection-manager/interfaces/markdown.ts +++ b/packages/core/client/src/collection-manager/interfaces/markdown.ts @@ -1,6 +1,7 @@ import { ISchema } from '@formily/react'; import { defaultProps } from './properties'; import { IField } from './types'; +import { i18n } from '../../i18n' export const markdown: IField = { name: 'markdown', @@ -25,4 +26,41 @@ export const markdown: IField = { schema['x-component-props']['ellipsis'] = true; } }, + validateSchema(fieldSchema) { + return { + max: { + type: 'number', + title: '{{ t("Max length") }}', + minimum: 0, + 'x-decorator': 'FormItem', + 'x-component': 'InputNumber', + 'x-component-props': { + precision: 0 + }, + 'x-reactions': `{{(field) => { + const targetValue = field.query('.min').value(); + field.selfErrors = + !!targetValue && !!field.value && targetValue > field.value ? '${i18n.t('Max length must greater than min length')}' : '' + }}}`, + }, + min: { + type: 'number', + title: '{{ t("Min length") }}', + minimum: 0, + 'x-decorator': 'FormItem', + 'x-component': 'InputNumber', + 'x-component-props': { + precision: 0 + }, + 'x-reactions': { + dependencies: ['.max'], + fulfill: { + state: { + selfErrors: `{{!!$deps[0] && !!$self.value && $deps[0] < $self.value ? '${i18n.t('Min length must less than max length')}' : ''}}`, + }, + }, + }, + }, + }; + } }; diff --git a/packages/core/client/src/collection-manager/interfaces/number.ts b/packages/core/client/src/collection-manager/interfaces/number.ts index eb5528bd2..3f441511e 100644 --- a/packages/core/client/src/collection-manager/interfaces/number.ts +++ b/packages/core/client/src/collection-manager/interfaces/number.ts @@ -1,5 +1,8 @@ +import { registerValidateRules } from '@formily/core'; +import { ISchema } from '@formily/react'; import { defaultProps, operators } from './properties'; import { IField } from './types'; +import { i18n } from '../../i18n'; export const number: IField = { name: 'number', @@ -42,4 +45,62 @@ export const number: IField = { filterable: { operators: operators.number, }, + validateSchema(fieldSchema) { + return { + maximum: { + type: 'number', + title: '{{ t("Maximum") }}', + 'x-decorator': 'FormItem', + 'x-component': 'InputNumber', + 'x-reactions': `{{(field) => { + const targetValue = field.query('.minimum').value(); + field.selfErrors = + !!targetValue && !!field.value && targetValue > field.value ? '${i18n.t('Maximum must greater than minimum')}' : '' + }}}`, + }, + minimum: { + type: 'number', + title: '{{ t("Minimum") }}', + 'x-decorator': 'FormItem', + 'x-component': 'InputNumber', + 'x-reactions': { + dependencies: ['.maximum'], + fulfill: { + state: { + selfErrors: `{{!!$deps[0] && !!$self.value && $deps[0] < $self.value ? '${i18n.t('Minimum must less than maximum')}' : ''}}`, + }, + }, + }, + }, + format: { + type: 'string', + title: '{{ t("Format") }}', + 'x-decorator': 'FormItem', + 'x-component': 'Select', + 'x-component-props': { + allowClear: true, + }, + enum: [{ + label: '{{ t("Integer") }}', + value: 'integer', + }, { + label: '{{ t("Odd") }}', + value: 'odd', + }, { + label: '{{ t("Even") }}', + value: 'even', + }] + }, + pattern: { + type: 'string', + title: '{{ t("Regular expression") }}', + 'x-decorator': 'FormItem', + 'x-component': 'Input', + 'x-component-props': { + prefix: '/', + suffix: '/', + } + }, + }; + } }; diff --git a/packages/core/client/src/collection-manager/interfaces/password.ts b/packages/core/client/src/collection-manager/interfaces/password.ts index 743c4b09d..21ae7d2d9 100644 --- a/packages/core/client/src/collection-manager/interfaces/password.ts +++ b/packages/core/client/src/collection-manager/interfaces/password.ts @@ -1,5 +1,7 @@ +import { ISchema } from '@formily/react'; import { defaultProps } from './properties'; import { IField } from './types'; +import { i18n } from '../../i18n'; export const password: IField = { name: 'password', @@ -19,4 +21,41 @@ export const password: IField = { properties: { ...defaultProps, }, + validateSchema(fieldSchema) { + return { + max: { + type: 'number', + title: '{{ t("Max length") }}', + minimum: 0, + 'x-decorator': 'FormItem', + 'x-component': 'InputNumber', + 'x-component-props': { + precision: 0 + }, + 'x-reactions': `{{(field) => { + const targetValue = field.query('.min').value(); + field.selfErrors = + !!targetValue && !!field.value && targetValue > field.value ? '${i18n.t('Max length must greater than min length')}' : '' + }}}`, + }, + min: { + type: 'number', + title: '{{ t("Min length") }}', + minimum: 0, + 'x-decorator': 'FormItem', + 'x-component': 'InputNumber', + 'x-component-props': { + precision: 0 + }, + 'x-reactions': { + dependencies: ['.max'], + fulfill: { + state: { + selfErrors: `{{!!$deps[0] && !!$self.value && $deps[0] < $self.value ? '${i18n.t('Min length must less than max length')}' : ''}}`, + }, + }, + }, + }, + }; + } }; diff --git a/packages/core/client/src/collection-manager/interfaces/percent.ts b/packages/core/client/src/collection-manager/interfaces/percent.ts index c16f7383d..d7c3c27ee 100644 --- a/packages/core/client/src/collection-manager/interfaces/percent.ts +++ b/packages/core/client/src/collection-manager/interfaces/percent.ts @@ -1,5 +1,51 @@ +import { ISchema } from '@formily/react'; import { defaultProps, operators } from './properties'; import { IField } from './types'; +import { i18n } from '../../i18n'; +import { registerValidateFormats, registerValidateRules, registerValidateLocale } from '@formily/core'; + +registerValidateRules({ + percentMode(value, rule) { + const { maxValue, minValue } = rule; + + if (maxValue) { + if (value > maxValue) { + return { + type: 'error', + message: `${i18n.t('The field value cannot be greater than ')}${maxValue * 100}%`, + } + } + } + + if (minValue) { + if (value < minValue) { + return { + type: 'error', + message: `${i18n.t('The field value cannot be less than ')}${minValue * 100}%`, + } + } + } + + return true; + }, + + percentFormats(value, rule) { + const { percentFormat } = rule; + + if (value && percentFormat === 'Integer' && /^-?[1-9]\d*$/.test((value * 100).toString()) === false) { + return { + type: 'error', + message: `${i18n.t('The field value is not an integer number')}`, + } + } + + return true; + } +}) + +// registerValidateFormats({ +// percentInteger: /^(\d+)(.\d{0,2})?$/, +// }); export const percent: IField = { name: 'percent', @@ -43,4 +89,62 @@ export const percent: IField = { filterable: { operators: operators.number, }, + validateSchema(fieldSchema) { + return { + maxValue: { + type: 'number', + title: '{{ t("Maximum") }}', + 'x-decorator': 'FormItem', + 'x-component': 'Percent', + 'x-component-props': { + addonAfter: '%', + }, + 'x-reactions': `{{(field) => { + const targetValue = field.query('.minimum').value(); + field.selfErrors = + !!targetValue && !!field.value && targetValue > field.value ? '${i18n.t('Maximum must greater than minimum')}' : '' + }}}`, + }, + minValue: { + type: 'number', + title: '{{ t("Minimum") }}', + 'x-decorator': 'FormItem', + 'x-component': 'Percent', + 'x-component-props': { + addonAfter: '%', + }, + 'x-reactions': { + dependencies: ['.maximum'], + fulfill: { + state: { + selfErrors: `{{!!$deps[0] && !!$self.value && $deps[0] < $self.value ? '${i18n.t('Minimum must less than maximum')}' : ''}}`, + }, + }, + }, + }, + percentFormat: { + type: 'string', + title: '{{ t("Format") }}', + 'x-decorator': 'FormItem', + 'x-component': 'Select', + 'x-component-props': { + allowClear: true, + }, + enum: [{ + label: '{{ t("Integer") }}', + value: 'Integer', + }] + }, + pattern: { + type: 'string', + title: '{{ t("Regular expression") }}', + 'x-decorator': 'FormItem', + 'x-component': 'Input', + 'x-component-props': { + prefix: '/', + suffix: '/', + } + }, + }; + } }; diff --git a/packages/core/client/src/collection-manager/interfaces/richText.ts b/packages/core/client/src/collection-manager/interfaces/richText.ts index 040252860..49903cd61 100644 --- a/packages/core/client/src/collection-manager/interfaces/richText.ts +++ b/packages/core/client/src/collection-manager/interfaces/richText.ts @@ -1,6 +1,7 @@ import type { ISchema } from '@formily/react'; import { defaultProps } from './properties'; import { IField } from './types'; +import { i18n } from '../../i18n'; export const richText: IField = { name: 'richText', @@ -26,4 +27,41 @@ export const richText: IField = { schema['x-component-props']['ellipsis'] = true; } }, + validateSchema(fieldSchema, formItemStyle) { + return { + max: { + type: 'number', + title: '{{ t("Max length") }}', + minimum: 0, + 'x-decorator': 'FormItem', + 'x-component': 'InputNumber', + 'x-component-props': { + precision: 0 + }, + 'x-reactions': `{{(field) => { + const targetValue = field.query('.min').value(); + field.selfErrors = + !!targetValue && !!field.value && targetValue > field.value ? '${i18n.t('Max length must greater than min length')}' : '' + }}}`, + }, + min: { + type: 'number', + title: '{{ t("Min length") }}', + minimum: 0, + 'x-decorator': 'FormItem', + 'x-component': 'InputNumber', + 'x-component-props': { + precision: 0 + }, + 'x-reactions': { + dependencies: ['.max'], + fulfill: { + state: { + selfErrors: `{{!!$deps[0] && !!$self.value && $deps[0] < $self.value ? '${i18n.t('Min length must less than max length')}' : ''}}`, + }, + }, + }, + }, + }; + } }; diff --git a/packages/core/client/src/collection-manager/interfaces/textarea.ts b/packages/core/client/src/collection-manager/interfaces/textarea.ts index 3561d51d6..e8bc46451 100644 --- a/packages/core/client/src/collection-manager/interfaces/textarea.ts +++ b/packages/core/client/src/collection-manager/interfaces/textarea.ts @@ -1,6 +1,7 @@ import { ISchema } from '@formily/react'; import { defaultProps } from './properties'; import { IField } from './types'; +import { i18n } from '../../i18n'; export const textarea: IField = { name: 'textarea', @@ -26,4 +27,41 @@ export const textarea: IField = { schema['x-component-props']['ellipsis'] = true; } }, + validateSchema(fieldSchema) { + return { + max: { + type: 'number', + title: '{{ t("Max length") }}', + minimum: 0, + 'x-decorator': 'FormItem', + 'x-component': 'InputNumber', + 'x-component-props': { + precision: 0 + }, + 'x-reactions': `{{(field) => { + const targetValue = field.query('.min').value(); + field.selfErrors = + !!targetValue && !!field.value && targetValue > field.value ? '${i18n.t('Max length must greater than min length')}' : '' + }}}`, + }, + min: { + type: 'number', + title: '{{ t("Min length") }}', + minimum: 0, + 'x-decorator': 'FormItem', + 'x-component': 'InputNumber', + 'x-component-props': { + precision: 0 + }, + 'x-reactions': { + dependencies: ['.max'], + fulfill: { + state: { + selfErrors: `{{!!$deps[0] && !!$self.value && $deps[0] < $self.value ? '${i18n.t('Min length must less than max length')}' : ''}}`, + }, + }, + }, + }, + }; + } }; diff --git a/packages/core/client/src/locale/en_US.ts b/packages/core/client/src/locale/en_US.ts index 165c09902..1dedad8d9 100644 --- a/packages/core/client/src/locale/en_US.ts +++ b/packages/core/client/src/locale/en_US.ts @@ -549,4 +549,5 @@ export default { "Field component": "Field component", "Subtable": "Subtable", "Subform": "Subform", + "Regular expression": "Pattern", } diff --git a/packages/core/client/src/locale/zh_CN.ts b/packages/core/client/src/locale/zh_CN.ts index 29169a261..cad175573 100644 --- a/packages/core/client/src/locale/zh_CN.ts +++ b/packages/core/client/src/locale/zh_CN.ts @@ -236,6 +236,25 @@ export default { "Default is the ID field": "默认为 ID 字段", "Set default sorting rules": "设置排序规则", + "Set validation rules": "设置验证规则", + "Max length": "最大长度", + "Min length": "最小长度", + "Maximum": "最大值", + "Minimum": "最小值", + "Max length must greater than min length": "最大长度必须大于最小长度", + "Min length must less than max length": "最小长度必须小于最大长度", + "Maximum must greater than minimum": "最大值必须大于最小值", + "Minimum must less than maximum": "最小值必须小于最大值", + "Validation rule": "验证规则", + "Add validation rule": "新增验证规则", + "Format": "格式", + "Regular expression": "正则表达式", + "Error message": "错误消息", + "Length": "长度", + "The field value cannot be greater than ": "数值不能大于", + "The field value cannot be less than ": "数值不能小于", + "The field value is not an integer number": "数字不是整数", + "is before": "早于", "is after": "晚于", "is on or after": "不早于", diff --git a/packages/core/client/src/schema-component/antd/form-item/FormItem.tsx b/packages/core/client/src/schema-component/antd/form-item/FormItem.tsx index 0365a7d52..bd6c9690f 100644 --- a/packages/core/client/src/schema-component/antd/form-item/FormItem.tsx +++ b/packages/core/client/src/schema-component/antd/form-item/FormItem.tsx @@ -1,5 +1,5 @@ import { css } from '@emotion/css'; -import { FormItem as Item } from '@formily/antd'; +import { ArrayCollapse, FormItem as Item, FormLayout } from '@formily/antd'; import { Field } from '@formily/core'; import { ISchema, useField, useFieldSchema } from '@formily/react'; import { uid } from '@formily/shared'; @@ -11,6 +11,7 @@ import { useCollection, useCollectionManager } from '../../../collection-manager import { GeneralSchemaDesigner, SchemaSettings } from '../../../schema-settings'; import { BlockItem } from '../block-item'; import { HTMLEncode } from '../input/shared'; +import * as _ from 'lodash'; const divWrap = (schema: ISchema) => { return { @@ -59,6 +60,7 @@ FormItem.Designer = (props) => { const compile = useCompile(); const collectionField = getField(fieldSchema['name']) || getCollectionJoinField(fieldSchema['x-collection-field']); const interfaceConfig = getInterface(collectionField?.interface); + const validateSchema = interfaceConfig?.['validateSchema']?.(fieldSchema); const originalTitle = collectionField?.uiSchema?.title; const targetFields = collectionField?.target ? getCollectionFields(collectionField.target) : []; const isSubFormAssocitionField = field.address.segments.includes('__form_grid'); @@ -81,6 +83,7 @@ FormItem.Designer = (props) => { if (fieldSchema['x-read-pretty'] === true) { readOnlyMode = 'read-pretty'; } + return ( {collectionField && ( @@ -201,6 +204,126 @@ FormItem.Designer = (props) => { }} /> )} + {validateSchema && ( + = 3}}' + } + } + } + }, + } + } + } + } as ISchema} + onSubmit={(v) => { + const rules = []; + for (const rule of v.rules) { + rules.push(_.pickBy(rule, _.identity)) + } + const schema = { + ['x-uid']: fieldSchema['x-uid'], + }; + // return; + // if (['number'].includes(collectionField?.interface) && collectionField?.uiSchema?.['x-component-props']?.['stringMode'] === true) { + // rules['numberStringMode'] = true; + // } + if (['percent'].includes(collectionField?.interface)) { + for (const rule of rules) { + if (!!rule.maxValue || !!rule.minValue) { + rule['percentMode'] = true; + } + + if (rule.percentFormat) { + rule['percentFormats'] = true; + } + } + } + const concatValidator = _.concat([], collectionField?.uiSchema?.['x-validator'] || [], rules) + field.validator = concatValidator; + fieldSchema['x-validator'] = rules; + schema['x-validator'] = rules; + dn.emit('patch', { + schema, + }); + refresh(); + }} + /> + )} {form && !isSubFormAssocitionField && ['o2o', 'oho', 'obo', 'o2m'].includes(collectionField?.interface) && ( { + const { onChange, ...others } = props; + const handleChange = (v) => { + onChange(parseFloat(v)); + } + return (); +}, mapReadPretty(ReadPretty)); export default InputNumber; diff --git a/packages/core/client/src/schema-component/antd/percent/Percent.tsx b/packages/core/client/src/schema-component/antd/percent/Percent.tsx index 39f223e2f..d7240d3e5 100644 --- a/packages/core/client/src/schema-component/antd/percent/Percent.tsx +++ b/packages/core/client/src/schema-component/antd/percent/Percent.tsx @@ -12,10 +12,10 @@ export const Percent = connect( { if (onChange) { - onChange(math.round(v / 100, 9)); + onChange(v ? math.round(v / 100, 9) : null); } }} /> diff --git a/packages/core/client/src/schema-component/antd/table-v2/Table.tsx b/packages/core/client/src/schema-component/antd/table-v2/Table.tsx index dbc4d7763..213ce603f 100644 --- a/packages/core/client/src/schema-component/antd/table-v2/Table.tsx +++ b/packages/core/client/src/schema-component/antd/table-v2/Table.tsx @@ -23,7 +23,6 @@ const useTableColumns = () => { const field = useField(); const schema = useFieldSchema(); const { exists, render } = useSchemaInitializer(schema['x-initializer']); - // console.log('useTableColumns', exists); const columns = schema .reduceProperties((buf, s) => { if (isColumnComponent(s)) { @@ -38,7 +37,6 @@ const useTableColumns = () => { } }, []); const dataIndex = collectionFields?.length > 0 ? collectionFields[0].name : s.name; - console.log('useTableColumns', s.name, s, field.value); return { title: , dataIndex, @@ -48,7 +46,6 @@ const useTableColumns = () => { render: (v, record) => { const index = field.value?.indexOf(record); // console.log((Date.now() - start) / 1000); - console.log('useTableColumns.index', index, record); return (