diff --git a/packages/core/client/src/collection-manager/Configuration/index.tsx b/packages/core/client/src/collection-manager/Configuration/index.tsx index 33d0bddb3..40b8a121c 100644 --- a/packages/core/client/src/collection-manager/Configuration/index.tsx +++ b/packages/core/client/src/collection-manager/Configuration/index.tsx @@ -1,4 +1,9 @@ +import { registerValidateFormats } from '@formily/core'; + export * from './AddFieldAction'; export * from './ConfigurationTable'; export * from './EditFieldAction'; +registerValidateFormats({ + uid: /^[A-Za-z0-9][A-Za-z0-9_-]*$/, +}); diff --git a/packages/core/client/src/collection-manager/Configuration/schemas/collections.ts b/packages/core/client/src/collection-manager/Configuration/schemas/collections.ts index cd742f978..7395b2ecd 100644 --- a/packages/core/client/src/collection-manager/Configuration/schemas/collections.ts +++ b/packages/core/client/src/collection-manager/Configuration/schemas/collections.ts @@ -1,8 +1,5 @@ import { ISchema, Schema } from '@formily/react'; -import { useTranslation } from 'react-i18next'; import { i18n } from '../../../i18n'; -import { useRecord } from '../../../record-provider'; -import { useCompile } from '../../../schema-component'; import { CollectionOptions } from '../../types'; import { collectionFieldSchema } from './collectionFields'; @@ -121,6 +118,7 @@ export const collectionSchema: ISchema = { name: { 'x-component': 'CollectionField', 'x-decorator': 'FormItem', + 'x-validator': 'uid', }, footer: { type: 'void', diff --git a/packages/core/client/src/collection-manager/interfaces/m2m.tsx b/packages/core/client/src/collection-manager/interfaces/m2m.tsx index 6f9827725..e69cf45bc 100644 --- a/packages/core/client/src/collection-manager/interfaces/m2m.tsx +++ b/packages/core/client/src/collection-manager/interfaces/m2m.tsx @@ -175,6 +175,7 @@ export const m2m: IField = { "{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}", 'x-decorator': 'FormItem', 'x-component': 'Input', + 'x-validator': 'uid', 'x-disabled': '{{ !createOnly }}', }, }, @@ -208,6 +209,7 @@ export const m2m: IField = { "{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}", 'x-decorator': 'FormItem', 'x-component': 'Input', + 'x-validator': 'uid', 'x-disabled': '{{ !createOnly }}', }, }, diff --git a/packages/core/client/src/collection-manager/interfaces/m2o.tsx b/packages/core/client/src/collection-manager/interfaces/m2o.tsx index bead8740b..98a7ff621 100644 --- a/packages/core/client/src/collection-manager/interfaces/m2o.tsx +++ b/packages/core/client/src/collection-manager/interfaces/m2o.tsx @@ -181,6 +181,7 @@ export const m2o: IField = { "{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}", 'x-decorator': 'FormItem', 'x-component': 'Input', + 'x-validator': 'uid', 'x-disabled': '{{ !createOnly }}', }, }, diff --git a/packages/core/client/src/collection-manager/interfaces/o2m.tsx b/packages/core/client/src/collection-manager/interfaces/o2m.tsx index 68b17c125..32dbc3937 100644 --- a/packages/core/client/src/collection-manager/interfaces/o2m.tsx +++ b/packages/core/client/src/collection-manager/interfaces/o2m.tsx @@ -207,6 +207,7 @@ export const o2m: IField = { "{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}", 'x-decorator': 'FormItem', 'x-component': 'Input', + 'x-validator': 'uid', 'x-disabled': '{{ !createOnly }}', }, }, diff --git a/packages/core/client/src/collection-manager/interfaces/o2o.tsx b/packages/core/client/src/collection-manager/interfaces/o2o.tsx index ced80ebe4..64f9b3458 100644 --- a/packages/core/client/src/collection-manager/interfaces/o2o.tsx +++ b/packages/core/client/src/collection-manager/interfaces/o2o.tsx @@ -198,6 +198,7 @@ export const o2o: IField = { "{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}", 'x-decorator': 'FormItem', 'x-component': 'Input', + 'x-validator': 'uid', 'x-disabled': '{{ !createOnly }}', }, }, @@ -362,6 +363,7 @@ export const oho: IField = { "{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}", 'x-decorator': 'FormItem', 'x-component': 'Input', + 'x-validator': 'uid', 'x-disabled': '{{ !createOnly }}', }, }, @@ -513,6 +515,7 @@ export const obo: IField = { "{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}", 'x-decorator': 'FormItem', 'x-component': 'Input', + 'x-validator': 'uid', 'x-disabled': '{{ !createOnly }}', }, }, diff --git a/packages/core/client/src/collection-manager/interfaces/properties/index.ts b/packages/core/client/src/collection-manager/interfaces/properties/index.ts index fa3a5b5a6..e1fd1ba94 100644 --- a/packages/core/client/src/collection-manager/interfaces/properties/index.ts +++ b/packages/core/client/src/collection-manager/interfaces/properties/index.ts @@ -218,6 +218,7 @@ export const defaultProps = { 'x-disabled': '{{ !createOnly }}', 'x-decorator': 'FormItem', 'x-component': 'Input', + 'x-validator': 'uid', description: "{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}", }, diff --git a/packages/core/database/src/fields/uid-field.ts b/packages/core/database/src/fields/uid-field.ts index 5010172ba..780da4409 100644 --- a/packages/core/database/src/fields/uid-field.ts +++ b/packages/core/database/src/fields/uid-field.ts @@ -8,17 +8,35 @@ export class UidField extends Field { } init() { - const { name, prefix = '' } = this.options; - const { model } = this.context.collection; - model.beforeCreate(async (instance) => { - if (!instance.get(name)) { + const { name, prefix = '', pattern } = this.options; + const re = new RegExp(pattern || '^[A-Za-z0-9][A-Za-z0-9_-]*$'); + this.listener = async (instance) => { + const value = instance.get(name); + if (!value) { instance.set(name, `${prefix}${uid()}`); + } else if (re.test(value)) { + instance.set(name, value); + } else { + throw new Error(`uid '${value}' is invalid`); } - }); + }; + } + + bind() { + super.bind(); + this.on('beforeCreate', this.listener); + this.on('beforeUpdate', this.listener); + } + + unbind() { + super.unbind(); + this.off('beforeCreate', this.listener); + this.off('beforeUpdate', this.listener); } } export interface UidFieldOptions extends BaseColumnFieldOptions { type: 'uid'; prefix?: string; + pattern?: string; } diff --git a/packages/plugins/users/src/collections/users.ts b/packages/plugins/users/src/collections/users.ts index 8a7626f6c..24c96d7f0 100644 --- a/packages/plugins/users/src/collections/users.ts +++ b/packages/plugins/users/src/collections/users.ts @@ -37,6 +37,7 @@ export default { type: 'string', title: '{{t("Email")}}', 'x-component': 'Input', + 'x-validator': 'email', require: true, }, },