Capacités courantes

L'objet contexte fournit les capacités intégrées de NocoBase. Cependant, certaines ne sont disponibles que dans le Plugin, d'autres uniquement dans les composants, et d'autres encore existent des deux côtés mais avec des syntaxes différentes. Vue d'ensemble :

CapacitéPlugin (this.xxx)Component (ctx.xxx)Description
Requêtes APIthis.context.apictx.apiUtilisation identique
Internationalisationthis.t() / this.context.tctx.tthis.t() injecte automatiquement le namespace
Logsthis.context.loggerctx.loggerUtilisation identique
Enregistrement de routethis.router.add()-Plugin uniquement
Navigation-ctx.router.navigate()Composant uniquement
Informations de routethis.context.locationctx.route / ctx.locationRecommandé d'utiliser dans les composants
Gestion de vuesthis.context.viewerctx.viewerOuvrir boîte de dialogue / tiroir, etc.
FlowEnginethis.flowEngine-Plugin uniquement

Détaillons par namespace.

Requêtes API (ctx.api)

ctx.api.request() appelle les API back-end avec une utilisation identique à Axios.

Dans le Plugin

import { Plugin } from '@nocobase/client-v2';

class MyPlugin extends Plugin {
  async load() {
    // Envoyer une requête directement dans load()
    const response = await this.context.api.request({
      url: 'app:getInfo',
      method: 'get',
    });
    console.log('Informations de l\'application', response.data);
  }
}

Dans un composant

import { useFlowContext } from '@nocobase/flow-engine';

export default function MyPage() {
  const ctx = useFlowContext();

  const handleLoad = async () => {
    // Requête GET
    const response = await ctx.api.request({
      url: 'users:list',
      method: 'get',
    });
    console.log(response.data);

    // Requête POST
    await ctx.api.request({
      url: 'users:create',
      method: 'post',
      data: { name: 'Tao Tao' },
    });
  };

  return <button onClick={handleLoad}>Charger les données</button>;
}

Avec ahooks useRequest

Dans un composant, vous pouvez utiliser useRequest d'ahooks pour simplifier la gestion des états de requête :

import { useFlowContext } from '@nocobase/flow-engine';
import { useRequest } from 'ahooks';

export default function PostList() {
  const ctx = useFlowContext();

  const { data, loading, error, refresh } = useRequest(() =>
    ctx.api.request({
      url: 'posts:list',
      method: 'get',
    }),
  );

  if (loading) return <div>Chargement...</div>;
  if (error) return <div>Erreur de requête : {error.message}</div>;

  return (
    <div>
      <button onClick={refresh}>Rafraîchir</button>
      <pre>{JSON.stringify(data?.data, null, 2)}</pre>
    </div>
  );
}

Intercepteurs de requêtes

ctx.api.axios permet d'ajouter des intercepteurs de requête/réponse, généralement configurés dans load() du Plugin :

async load() {
  // Intercepteur de requête : ajouter un en-tête personnalisé
  this.context.api.axios.interceptors.request.use((config) => {
    config.headers['X-Custom-Header'] = 'my-value';
    return config;
  });

  // Intercepteur de réponse : gestion d'erreur globale
  this.context.api.axios.interceptors.response.use(
    (response) => response,
    (error) => {
      console.error('Erreur de requête', error);
      return Promise.reject(error);
    },
  );
}

En-têtes de requête personnalisés NocoBase

Le serveur NocoBase prend en charge les en-têtes personnalisés suivants, généralement injectés automatiquement par les intercepteurs et qu'il n'est pas nécessaire de définir à la main :

HeaderDescription
X-AppEn multi-app, indique l'application courante
X-LocaleLangue courante (par exemple zh-CN, en-US)
X-HostnameNom d'hôte du client
X-TimezoneFuseau horaire du client (par exemple +08:00)
X-RoleRôle courant
X-AuthenticatorMode d'authentification de l'utilisateur courant

Internationalisation (ctx.t / ctx.i18n)

Les plugins NocoBase gèrent leurs fichiers multilingues via le répertoire src/locale/, et utilisent ctx.t() pour récupérer les traductions dans le code.

Fichiers multilingues

Sous src/locale/ du plugin, créez un fichier JSON par langue :

plugin-hello/
└── src/
    └── locale/
        ├── zh-CN.json
        └── en-US.json
// zh-CN.json
{
  "Hello": "你好",
  "Your name is {{name}}": "你的名字是 {{name}}"
}
// en-US.json
{
  "Hello": "Hello",
  "Your name is {{name}}": "Your name is {{name}}"
}
Attention

L'ajout initial des fichiers de langue nécessite un redémarrage de l'application pour prendre effet.

ctx.t()

Dans un composant, ctx.t() renvoie le texte traduit :

const ctx = useFlowContext();

// Utilisation de base
ctx.t('Hello');

// Avec variable
ctx.t('Your name is {{name}}', { name: 'NocoBase' });

// Avec namespace explicite (par défaut, le namespace est le nom du package du plugin)
ctx.t('Hello', { ns: '@my-project/plugin-hello' });

this.t()

Dans le Plugin, this.t() est plus pratique — il injecte automatiquement le nom du package du plugin comme namespace, sans avoir à passer ns à la main :

class MyPlugin extends Plugin {
  async load() {
    // Utilise automatiquement le nom du package du plugin courant comme ns
    console.log(this.t('Hello'));

    // Équivalent à
    console.log(this.context.t('Hello', { ns: '@my-project/plugin-hello' }));
  }
}

ctx.i18n

ctx.i18n est l'instance i18next sous-jacente. En général, ctx.t() suffit. Mais si vous devez changer de langue dynamiquement ou écouter les changements de langue, utilisez ctx.i18n :

// Récupérer la langue courante
const currentLang = ctx.i18n.language; // 'zh-CN'

// Écouter les changements de langue
ctx.i18n.on('languageChanged', (lng) => {
  console.log('Langue changée pour', lng);
});

tExpr()

tExpr() génère une chaîne d'expression de traduction différée, généralement utilisée dans FlowModel.define() — car define s'exécute au chargement du module, sans instance i18n disponible :

import { tExpr } from '@nocobase/flow-engine';

HelloBlockModel.define({
  label: tExpr('Hello block'), // produit '{{t("Hello block")}}', traduit à l'exécution
});

Pour des utilisations d'internationalisation plus complètes (écriture des fichiers de traduction, hook useT, tExpr, etc.), voir Internationalisation i18n. Liste complète des codes de langue supportés par NocoBase : Liste des langues.

Logs (ctx.logger)

ctx.logger produit des logs structurés, basés sur pino.

Dans le Plugin

import { Plugin } from '@nocobase/client-v2';

class MyPlugin extends Plugin {
  async load() {
    this.context.logger.info('Plugin chargé', { plugin: 'my-plugin' });
    this.context.logger.error('Échec d\'initialisation', { error });
  }
}

Dans un composant

import { useFlowContext } from '@nocobase/flow-engine';

export default function MyPage() {
  const ctx = useFlowContext();

  const handleLoad = async () => {
    ctx.logger.info('Page chargée', { page: 'UserList' });
    ctx.logger.debug('État utilisateur courant', { user });
  };

  // ...
}

Niveaux de log du plus haut au plus bas : fatal > error > warn > info > debug > trace. Seuls les logs supérieurs ou égaux au niveau configuré sont émis.

Routes (ctx.router / ctx.route / ctx.location)

Les capacités liées aux routes se divisent en trois parties : enregistrement (Plugin uniquement), navigation et récupération d'informations (composant uniquement).

Enregistrement de routes (this.router / this.pluginSettingsManager)

Dans load() du Plugin, enregistrez les routes de page via this.router.add() et les pages de configuration de plugin via this.pluginSettingsManager :

async load() {
  // Enregistrer une route de page standard
  this.router.add('hello', {
    path: '/hello',
    componentLoader: () => import('./pages/HelloPage'),
  });

  // Enregistrer la page de configuration du plugin (apparaîtra dans le menu « Configuration des plugins »)
  this.pluginSettingsManager.addMenuItem({
    key: 'my-settings',
    title: this.t('My Settings'),
    icon: 'SettingOutlined', // Icône Ant Design, voir https://5x.ant.design/components/icon
  });
  this.pluginSettingsManager.addPageTabItem({
    menuKey: 'my-settings',
    key: 'index',
    title: this.t('My Settings'),
    componentLoader: () => import('./pages/MySettingsPage'),
  });
}

Voir Router pour les détails. Exemple complet de page de configuration : Faire une page de configuration de plugin.

Attention

this.router est le RouterManager, utilisé pour enregistrer des routes. this.pluginSettingsManager est le PluginSettingsManager, utilisé pour enregistrer la page de configuration. Les deux ne sont pas la même chose que ctx.router (React Router, utilisé pour la navigation) dans les composants.

Dans un composant, naviguez via ctx.router.navigate() :

const ctx = useFlowContext();
ctx.router.navigate('/hello'); // -> /v/hello

Informations de route (ctx.route)

Dans un composant, récupérez les informations de la route courante via ctx.route :

const ctx = useFlowContext();

// Récupère le paramètre dynamique (par exemple route définie /users/:id)
const { id } = ctx.route.params;

// Récupère le nom de la route
const { name } = ctx.route;

Type complet de ctx.route :

interface RouteOptions {
  name?: string;         // Identifiant unique de la route
  path?: string;         // Modèle de route
  pathname?: string;     // Chemin complet de la route
  params?: Record<string, any>; // Paramètres de la route
}

URL courante (ctx.location)

ctx.location fournit les détails de l'URL courante, similaire à window.location du navigateur :

const ctx = useFlowContext();

console.log(ctx.location.pathname); // '/v/hello'
console.log(ctx.location.search);   // '?page=1'
console.log(ctx.location.hash);     // '#section'

ctx.route et ctx.location sont aussi accessibles via this.context dans le Plugin, mais l'URL au moment du chargement du plugin est indéterminée et la valeur n'a pas de sens. Il est recommandé de les utiliser dans les composants.

Gestion des vues (ctx.viewer / ctx.view)

ctx.viewer permet d'ouvrir des boîtes de dialogue, des tiroirs, etc. de façon impérative. Disponible aussi bien dans le Plugin que dans les composants.

Dans le Plugin

import { Plugin } from '@nocobase/client-v2';

class MyPlugin extends Plugin {
  async load() {
    // Par exemple, ouvrir une boîte de dialogue dans une logique d'initialisation
    this.context.viewer.dialog({
      title: 'Bienvenue',
      content: () => <div>Plugin initialisé</div>,
    });
  }
}

Dans un composant

import { Button } from 'antd';
import { useFlowContext } from '@nocobase/flow-engine';

export default function MyPage() {
  const ctx = useFlowContext();

  const openDetail = () => {
    // Ouvrir une boîte de dialogue
    ctx.viewer.dialog({
      title: 'Modifier l\'utilisateur',
      content: () => <UserEditForm />,
    });
  };

  const openDrawer = () => {
    // Ouvrir un tiroir
    ctx.viewer.drawer({
      title: 'Détails',
      content: () => <UserDetail />,
    });
  };

  return (
    <div>
      <Button onClick={openDetail}>Modifier</Button>
      <Button onClick={openDrawer}>Voir les détails</Button>
    </div>
  );
}

Méthode générique

// Spécifier le type de vue via type
ctx.viewer.open({
  type: 'dialog',  // 'dialog' | 'drawer' | 'popover' | 'embed'
  title: 'Titre',
  content: () => <SomeComponent />,
});

Manipuler la vue depuis l'intérieur (ctx.view)

Dans un composant à l'intérieur d'une boîte de dialogue ou d'un tiroir, vous pouvez manipuler la vue courante (par exemple la fermer) via ctx.view :

import { Button } from 'antd';
import { useFlowContext } from '@nocobase/flow-engine';

function DialogContent() {
  const ctx = useFlowContext();
  return (
    <div>
      <p>Contenu de la boîte de dialogue</p>
      <Button onClick={() => ctx.view.close()}>Fermer</Button>
    </div>
  );
}

FlowEngine (this.flowEngine)

this.flowEngine est l'instance FlowEngine, disponible uniquement dans le Plugin. On l'utilise généralement pour enregistrer des FlowModel :

import { Plugin } from '@nocobase/client-v2';

class MyPlugin extends Plugin {
  async load() {
    // Enregistrer un FlowModel (chargement à la demande recommandé)
    this.flowEngine.registerModelLoaders({
      HelloBlockModel: {
        loader: () => import('./models/HelloBlockModel'),
      },
    });
  }
}

FlowModel est le cœur du système de configuration visuelle de NocoBase — si votre composant doit apparaître dans le menu « Ajouter un bloc / champ / action », il faut l'encapsuler avec FlowModel. Voir FlowEngine pour les détails.

Autres capacités

Les capacités suivantes peuvent être utiles dans des scénarios plus avancés ; les voici brièvement listées :

PropriétéDescription
ctx.modelInstance FlowModel courante (disponible dans le contexte d'exécution d'un Flow)
ctx.refRéférence du composant, à utiliser avec ctx.onRefReady
ctx.exit()Sortir de l'exécution du Flow courant
ctx.defineProperty()Ajouter dynamiquement une propriété personnalisée au contexte
ctx.defineMethod()Ajouter dynamiquement une méthode personnalisée au contexte
ctx.useResource()Récupérer l'interface d'opération sur les ressources de données
ctx.dataSourceManagerGestion des sources de données

Pour les détails, voir Documentation complète FlowEngine.

Liens connexes