Novos Recursos
Suporte a Múltiplas Fontes de Dados
Adicionado o plugin ”Gerenciador de Fontes de Dados”, usado para gerenciar todas as coleções e campos das fontes de dados. O plugin Gerenciador de Fontes de Dados fornece uma interface centralizada para gerenciar fontes de dados e não oferece a capacidade de acessar as fontes de dados. Ele precisa ser usado em conjunto com vários plugins de fonte de dados. As fontes de dados atualmente suportadas incluem:
- Banco de Dados Principal: Banco de dados principal do NocoBase, suportando bancos de dados relacionais como MySQL, PostgreSQL, SQLite, etc.
- Fonte de Dados MySQL Externa: Acessar um banco de dados MySQL existente como fonte de dados.
- Fonte de Dados MariaDB Externa: Acessar um banco de dados MariaDB existente como fonte de dados.
- Fonte de Dados PostgreSQL Externa: Acessar um banco de dados PostgreSQL existente como fonte de dados.
Além disso, mais fontes de dados podem ser estendidas, podendo ser tipos comuns de bancos de dados ou plataformas que fornecem APIs (SDKs).

Ajuste no Gerenciamento de Coleções
Moveu o original “Gerenciador de Coleções” para “Fonte de Dados > Banco de Dados Principal > Configuração”.

Suporte para Campos Não-ID como Chave Primária e Restrições de Relacionamento
Ao criar uma coleção, você pode optar por não criar um campo ID.

Campos inteiros podem ser usados como chaves primárias.

Campos de texto de linha única também podem ser usados como chaves primárias.

As restrições de relacionamento suportam a seleção de outros campos com índice Único definido como campos não-chave primária.

Ajuste na Ordenação por Arrastar e Soltar
Adicionado um campo do tipo “Ordenação”. Os campos de ordenação não são mais gerados automaticamente ao criar coleções e precisam ser criados manualmente.

Ao selecionar um campo como grupo, o agrupamento será feito antes da ordenação.

Ao ativar a ordenação por arrastar e soltar no bloco de tabela, você precisa selecionar o campo de ordenação.

Ao criar um bloco Kanban, você precisa selecionar o campo de ordenação.

Ajuste nas Interfaces de Usuário e Permissão
Adicionada interface de gerenciamento de usuários e unificado o gerenciamento de usuários e funções sob um único menu.

Ajustada a interface de gerenciamento de funções para facilitar o gerenciamento de funções associadas a usuários, permissões, departamentos, etc.

Movido o original “Permissões de Ação” para a aba “Fonte de Dados”.

Plugin de Departamento

Organize usuários por departamentos, defina relações hierárquicas, vincule funções para controlar permissões e use departamentos como variáveis em fluxos de trabalho e expressões.
Fluxo de Trabalho: Aprovação
O plugin de aprovação fornece tipos de fluxo de trabalho dedicados (gatilhos) “Iniciar Aprovação” e nós de “Aprovação” para este processo. Combinado com as tabelas de dados personalizadas e blocos personalizados exclusivos do NocoBase, vários cenários de aprovação podem ser rápida e flexivelmente criados e gerenciados.
Configuração de aprovação

Processo de aprovação

Mais detalhes podem ser encontrados na documentação: Aprovação de Fluxo de Trabalho
Fluxo de Trabalho: Nó de Finalização de Processo
Este nó finaliza imediatamente a execução atual do fluxo de trabalho quando executado e termina com o status configurado no nó. É tipicamente usado para controle de fluxo lógico específico, para sair do fluxo de trabalho atual após atender certas condições lógicas, sem continuar com o processamento subsequente. Pode ser comparado ao comando return em linguagens de programação, usado para sair da função atualmente em execução.

Mais detalhes podem ser encontrados na documentação: Nó de Finalização de Processo
Fluxo de Trabalho: Nó de Variável Personalizada
Variáveis podem ser declaradas no fluxo de trabalho ou valores podem ser atribuídos a variáveis declaradas anteriormente, tipicamente usado para armazenar dados temporários no fluxo de trabalho. É adequado para cenários onde os resultados do cálculo precisam ser armazenados para uso posterior fora do branch (como loops, paralelismo, etc.).

Mais detalhes podem ser encontrados na documentação: Nó de Variável Personalizada
Fluxo de Trabalho: Interceptador de Requisição
O plugin interceptador de requisição fornece um mecanismo para interceptar operações em formulários, onde o evento de interceptação é acionado após a operação de formulário correspondente ser submetida e antes de ser processada. Se um nó “Finalizar Processo” for executado no fluxo de processo subsequente após o acionamento, ou se outros nós falharem na execução (erros ou outras execuções incompletas), a operação do formulário será interceptada; caso contrário, a operação agendada será executada normalmente. Pode ser usado para validação de negócios ou verificações lógicas para aprovar ou interceptar operações de criação, atualização e exclusão submetidas pelo cliente.

Mais detalhes podem ser encontrados na documentação: Interceptador de Requisição
Fluxo de Trabalho: Nó de Mensagem de Resposta
O nó de mensagem de resposta é usado para fornecer feedback ao cliente com mensagens personalizadas em tipos específicos de fluxos de trabalho (como interceptação de requisição e eventos de formulário).
Configuração do nó

Mensagem de aviso

Mais detalhes podem ser encontrados na documentação: Nó de Mensagem de Resposta
Mudanças Incompatíveis
APIs com Nomes Conflitantes
Nesta mudança de kernel, algumas APIs da nova versão entram em conflito com os nomes da versão antiga. Essas APIs conflitantes da versão antiga serão mantidas nesta versão, mas serão uniformemente sufixadas com _deprecated.
| API Original | API Obsoleta | Nova API |
|---|---|---|
| CollectionProvider | CollectionProvider_deprecated | CollectionProvider |
| useCollection | useCollection_deprecated | useCollection |
| useCollectionField | useCollectionField_deprecated | useCollectionField |
| useCollectionManager | useCollectionManager_deprecated | useCollectionManager |
| useContext(CollectionManagerContext) | useCollectionManager_deprecated | useCollectionManager |
Se você está usando as APIs relacionadas acima, você tem duas maneiras de mudar:
- Substituição simples: Substitua a API original pela que tem o sufixo
_deprecated, por exemplo, substituauseCollection()poruseRecord_deprecated(). - Use a nova API de acordo com a nova documentação: Embora os nomes das novas APIs sejam os mesmos das APIs antigas, há diferenças nos parâmetros e valores de retorno. Você precisa consultar a nova documentação
para ajustar o código correspondente.
Outras APIs que Requerem Ajuste
registerTemplate()mudou paraapp.dataSourceManager.addCollectionTemplates()registerField()mudou paraapp.dataSourceManager.addFieldInterfaces()registerGroup()mudou paraapp.dataSourceManager.addFieldInterfaceGroups()useContext(CollectionManagerContext)mudou parauseCollectionManager_deprecated()- Estender coleções usando
ExtendCollectionsProvider RecordProviderrequer a passagem explícita do parâmetro parent quando necessário
Exemplos de Mudança
Extensão de Template de Coleção
Definição
Anteriormente definido como um objeto, agora precisa ser alterado para uma classe. Por exemplo:
Antes:
import { ICollectionTemplate } from '@nocobase/client';
const calendar: ICollectionTemplate = {
name: 'calendar',
title: 'Calendar collection',
order: 2,
color: 'orange',
// ...
}
Agora:
import { CollectionTemplate } from '@nocobase/client';
class CalendarCollectionTemplate extends CollectionTemplate {
name = 'calendar';
title = 'Calendar collection';
order = 2;
color = 'orange';
}
As propriedades do objeto original tornam-se membros da classe.
Registro
Anteriormente registrado através de registerTemplate, agora precisa ser registrado através do dataSourceManager.addCollectionTemplates do plugin. Por exemplo:
Antes:
import { registerTemplate } from '@nocobase/client';
import { calendar } from './calendar'
registerTemplate('calendar', calendar);
Agora:
import { Plugin } from '@nocobase/client';
import { CalendarCollectionTemplate } from './calendar'
export class CalendarPluginClient extends Plugin {
async load() {
this.app.dataSourceManager.addCollectionTemplates([CalendarCollectionTemplate]);
}
}
Extensão de Interface de Campo
Definição
Anteriormente definido como um objeto, agora precisa ser alterado para uma classe. Por exemplo:
Antes:
import { IField } from '@nocobase/client';
const attachment: IField = {
name: 'attachment',
type: 'object',
group: 'media',
title: 'Attachment',
// ...
}
Agora:
import { CollectionFieldInterface } from '@nocobase/client';
class AttachmentFieldInterface extends CollectionFieldInterface {
name = 'attachment';
type = 'object';
group = 'media';
title = 'Attachment';
// ...
}
As propriedades do objeto original tornam-se membros da classe.
Registro
Anteriormente registrado através de registerField, agora precisa ser registrado através do dataSourceManager.addFieldInterfaces do plugin e não requer a passagem de CollectionManagerProvider novamente. Por exemplo:
Antes:
import { registerField } from '@nocobase/client';
import { attachment } from './attachment'
- registerField(attachment.group, 'attachment', attachment);
export const FileManagerProvider: FC = (props) => {
return (
- <CollectionManagerProvider interfaces={{ attachment }}>
<SchemaComponentOptions scope={hooks} components={{ UploadActionInitializer }}>
{props.children}
</SchemaComponentOptions>
- </CollectionManagerProvider>
);
};
Agora:
import { Plugin } from '@nocobase/client';
import { AttachmentFieldInterface } from './attachment'
export class FilPlugin extends Plugin {
async load() {
this.app.dataSourceManager.addFieldInterfaces([AttachmentFieldInterface]);
}
}
Extensão de Grupo de Interface de Campo
Anteriormente registrado através de registerGroup, agora precisa ser registrado através do dataSourceManager.addFieldInterfaceGroups do plugin. Por exemplo:
- import { registerGroup, Plugin } from '@nocobase/client';
+ import { Plugin } from '@nocobase/client';
- registerGroup('map', {
- label: 'Map-based geometry',
- order: 10
- })
export class MapPlugin extends Plugin {
async load() {
+ this.app.dataSourceManager.addFieldInterfaceGroups({
+ map: {
+ label: generateNTemplate('Map-based geometry'),
+ order: 51,
+ },
+ });
}
}
useContext(CollectionManagerContext) Mudou para useCollectionManager_deprecated()
- const ctx = useContext(CollectionManagerContext);
+ const ctx = useCollectionManager_deprecated();
Estender Coleções, Use ExtendCollectionsProvider em Vez de CollectionManagerProvider
const Demo = () => {
- <CollectionManagerProvider collections={[apiKeysCollection]}>
+ <ExtendCollectionsProvider collections={[apiKeysCollection]}>
...
- </CollectionManagerProvider>
+ </ExtendCollectionsProvider>
}
Mudanças no RecordProvider
Anteriormente, quando a propriedade parent não era passada, o valor do último RecordProvider era automaticamente recuperado como parent. Agora, o parent precisa ser passado explicitamente, e quando o parent não é passado, o valor do parent será undefined.
- <RecordProvider record={recordData}>
+ <RecordProvider record={recordData} parent={parentRecordData}>
...
</RecordProvider>
Se não houver bagagem histórica, você também pode usar diretamente CollectionRecordProvider para substituir.
- <RecordProvider record={recordData}>
+ <CollectionRecordProvider record={recordData} parent={parentRecordData}>
...
- </RecordProvider>
+ </CollectionRecordProvider>
⚠️Diferença Entre RecordProvider e CollectionRecordProvider
- RecordProvider está obsoleto e será removido no futuro.
- RecordProvider carrega o antigo RecordContext, enquanto CollectionRecordProvider não.