Häufige Fähigkeiten

Das Kontext-Objekt stellt die eingebauten Fähigkeiten von NocoBase bereit. Beachten Sie: Manche sind nur im Plugin verfügbar, manche nur im Component, manche in beiden, aber mit unterschiedlicher Schreibweise. Hier ein Überblick:

FähigkeitPlugin (this.xxx)Component (ctx.xxx)Hinweis
API-Anfragethis.context.apictx.apiGleiche Verwendung
Internationalisierungthis.t() / this.context.tctx.tthis.t() fügt Plugin-Namespace automatisch ein
Loggingthis.context.loggerctx.loggerGleiche Verwendung
Routen-Registrierungthis.router.add()-Nur Plugin
Seitennavigation-ctx.router.navigate()Nur Component
Routen-Infothis.context.locationctx.route / ctx.locationEmpfohlen im Component zu verwenden
View-Verwaltungthis.context.viewerctx.viewerModal / Drawer öffnen usw.
FlowEnginethis.flowEngine-Nur Plugin

Im Folgenden werden die Fähigkeiten nach Namespace einzeln vorgestellt.

API-Anfragen (ctx.api)

Über ctx.api.request() rufen Sie Backend-Schnittstellen auf, die Verwendung entspricht Axios.

Verwendung in einem Plugin

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

class MyPlugin extends Plugin {
  async load() {
    // Direkt in load() Anfragen senden
    const response = await this.context.api.request({
      url: 'app:getInfo',
      method: 'get',
    });
    console.log('Anwendungsinformationen', response.data);
  }
}

Verwendung in einem Component

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

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

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

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

  return <button onClick={handleLoad}>Daten laden</button>;
}

In Kombination mit ahooks useRequest

In Components können Sie useRequest von ahooks verwenden, um die Zustandsverwaltung von Anfragen zu vereinfachen:

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>Wird geladen...</div>;
  if (error) return <div>Anfragefehler: {error.message}</div>;

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

Anfrage-Interceptors

Über ctx.api.axios können Sie Request- bzw. Response-Interceptors hinzufügen, üblicherweise im load() des Plugins:

async load() {
  // Request-Interceptor: benutzerdefinierten Header hinzufügen
  this.context.api.axios.interceptors.request.use((config) => {
    config.headers['X-Custom-Header'] = 'my-value';
    return config;
  });

  // Response-Interceptor: einheitliche Fehlerbehandlung
  this.context.api.axios.interceptors.response.use(
    (response) => response,
    (error) => {
      console.error('Anfragefehler', error);
      return Promise.reject(error);
    },
  );
}

Benutzerdefinierte Header von NocoBase

Der NocoBase Server unterstützt die folgenden benutzerdefinierten Header, die üblicherweise automatisch durch Interceptors eingefügt werden und nicht manuell gesetzt werden müssen:

HeaderHinweis
X-AppBei Multi-App-Szenarien gibt die aktuell zugegriffene App an
X-LocaleAktuelle Sprache (z. B. zh-CN, en-US)
X-HostnameHostname des Clients
X-TimezoneZeitzone des Clients (z. B. +08:00)
X-RoleAktuelle Rolle
X-AuthenticatorAktuelle Benutzer-Authentifizierungsart

Internationalisierung (ctx.t / ctx.i18n)

NocoBase-Plugins verwalten Mehrsprachen-Dateien über das Verzeichnis src/locale/ und verwenden im Code Übersetzungen über ctx.t().

Mehrsprachen-Dateien

Erstellen Sie unter src/locale/ des Plugins JSON-Dateien je Sprache:

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}}"
}
Hinweis

Beim erstmaligen Hinzufügen einer Sprachdatei muss die Anwendung neu gestartet werden, damit sie wirksam wird.

ctx.t()

Im Component erhalten Sie übersetzte Texte über ctx.t():

const ctx = useFlowContext();

// Grundlegende Verwendung
ctx.t('Hello');

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

// Mit angegebenem Namespace (Standard ist der Plugin-Paketname)
ctx.t('Hello', { ns: '@my-project/plugin-hello' });

this.t()

Im Plugin ist this.t() praktischer — es fügt automatisch den Plugin-Paketnamen als Namespace ein, sodass Sie ns nicht manuell übergeben müssen:

class MyPlugin extends Plugin {
  async load() {
    // Verwendet automatisch den aktuellen Plugin-Paketnamen als ns
    console.log(this.t('Hello'));

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

ctx.i18n

ctx.i18n ist die zugrundeliegende i18next-Instanz. Im Allgemeinen reicht ctx.t(). Wenn Sie jedoch dynamisch die Sprache wechseln, Sprachänderungen abhören usw. müssen, können Sie ctx.i18n verwenden:

// Aktuelle Sprache abrufen
const currentLang = ctx.i18n.language; // 'zh-CN'

// Sprachänderung abhören
ctx.i18n.on('languageChanged', (lng) => {
  console.log('Sprache gewechselt zu', lng);
});

tExpr()

tExpr() erzeugt verzögerte Übersetzungsausdrücke als Zeichenkette und wird typischerweise in FlowModel.define() verwendet — denn define wird beim Laden des Moduls ausgeführt, zu diesem Zeitpunkt existiert noch keine i18n-Instanz:

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

HelloBlockModel.define({
  label: tExpr('Hello block'), // Erzeugt '{{t("Hello block")}}', wird zur Laufzeit übersetzt
});

Vollständige Verwendung der Internationalisierung (Schreibweise von Übersetzungsdateien, useT-Hook, tExpr usw.) siehe i18n Internationalisierung. Vollständige Liste der von NocoBase unterstützten Sprachcodes siehe Sprachenliste.

Logging (ctx.logger)

Über ctx.logger werden strukturierte Logs ausgegeben, basierend auf pino.

Verwendung in einem Plugin

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

class MyPlugin extends Plugin {
  async load() {
    this.context.logger.info('Plugin geladen', { plugin: 'my-plugin' });
    this.context.logger.error('Initialisierung fehlgeschlagen', { error });
  }
}

Verwendung in einem Component

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

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

  const handleLoad = async () => {
    ctx.logger.info('Seite geladen', { page: 'UserList' });
    ctx.logger.debug('Aktueller Benutzerstatus', { user });
  };

  // ...
}

Log-Level von hoch nach niedrig: fatal > error > warn > info > debug > trace. Nur Logs, die größer oder gleich dem aktuell konfigurierten Level sind, werden ausgegeben.

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

Routen-bezogene Fähigkeiten gliedern sich in drei Bereiche: Registrierung (nur Plugin), Navigation und Informationsabruf (nur Component).

Routen-Registrierung (this.router / this.pluginSettingsManager)

In load() des Plugins registrieren Sie Seitenrouten über this.router.add() und Plugin-Einstellungsseiten über this.pluginSettingsManager:

async load() {
  // Normale Seitenroute registrieren
  this.router.add('hello', {
    path: '/hello',
    componentLoader: () => import('./pages/HelloPage'),
  });

  // Plugin-Einstellungsseite registrieren (erscheint im Menü „Plugin-Konfiguration")
  this.pluginSettingsManager.addMenuItem({
    key: 'my-settings',
    title: this.t('My Settings'),
    icon: 'SettingOutlined', // Ant Design-Icon, siehe https://5x.ant.design/components/icon
  });
  this.pluginSettingsManager.addPageTabItem({
    menuKey: 'my-settings',
    key: 'index',
    title: this.t('My Settings'),
    componentLoader: () => import('./pages/MySettingsPage'),
  });
}

Ausführliche Verwendung siehe Router. Vollständiges Beispiel einer Einstellungsseite siehe Eine Plugin-Einstellungsseite erstellen.

Hinweis

this.router ist der RouterManager und dient zum Registrieren von Routen. this.pluginSettingsManager ist der PluginSettingsManager und dient zum Registrieren von Einstellungsseiten. Beide sind nicht dasselbe wie ctx.router (React Router, dient zur Seitennavigation) im Component.

Seitennavigation (ctx.router)

Im Component navigieren Sie über ctx.router.navigate() zu einer anderen Seite:

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

Routen-Informationen (ctx.route)

Im Component erhalten Sie über ctx.route Informationen zur aktuellen Route:

const ctx = useFlowContext();

// Dynamische Parameter abrufen (z. B. mit der Routendefinition /users/:id)
const { id } = ctx.route.params;

// Routennamen abrufen
const { name } = ctx.route;

Vollständiger Typ von ctx.route:

interface RouteOptions {
  name?: string;         // Eindeutige Routen-ID
  path?: string;         // Routenvorlage
  pathname?: string;     // Vollständiger Pfad der Route
  params?: Record<string, any>; // Routenparameter
}

Aktuelle URL (ctx.location)

ctx.location stellt detaillierte Informationen zur aktuellen URL bereit, ähnlich dem window.location des Browsers:

const ctx = useFlowContext();

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

Auch wenn ctx.route und ctx.location über this.context im Plugin zugänglich sind, ist die URL beim Plugin-Laden unbestimmt und die abgerufenen Werte ohne Bedeutung. Verwendung im Component empfohlen.

View-Verwaltung (ctx.viewer / ctx.view)

ctx.viewer bietet die Möglichkeit, Modals, Drawer und andere Views imperativ zu öffnen. Verfügbar sowohl im Plugin als auch im Component.

Verwendung in einem Plugin

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

class MyPlugin extends Plugin {
  async load() {
    // Beispielsweise in einer Initialisierungslogik ein Modal öffnen
    this.context.viewer.dialog({
      title: 'Willkommen',
      content: () => <div>Plugin-Initialisierung abgeschlossen</div>,
    });
  }
}

Verwendung in einem Component

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

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

  const openDetail = () => {
    // Modal öffnen
    ctx.viewer.dialog({
      title: 'Benutzer bearbeiten',
      content: () => <UserEditForm />,
    });
  };

  const openDrawer = () => {
    // Drawer öffnen
    ctx.viewer.drawer({
      title: 'Details',
      content: () => <UserDetail />,
    });
  };

  return (
    <div>
      <Button onClick={openDetail}>Bearbeiten</Button>
      <Button onClick={openDrawer}>Details ansehen</Button>
    </div>
  );
}

Allgemeine Methode

// Über type den View-Typ angeben
ctx.viewer.open({
  type: 'dialog',  // 'dialog' | 'drawer' | 'popover' | 'embed'
  title: 'Titel',
  content: () => <SomeComponent />,
});

In einem View arbeiten (ctx.view)

In Components innerhalb eines Modals/Drawers können Sie über ctx.view den aktuellen View steuern (z. B. schließen):

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

function DialogContent() {
  const ctx = useFlowContext();
  return (
    <div>
      <p>Modal-Inhalt</p>
      <Button onClick={() => ctx.view.close()}>Schließen</Button>
    </div>
  );
}

FlowEngine (this.flowEngine)

this.flowEngine ist die FlowEngine-Instanz und nur im Plugin verfügbar. Üblicherweise wird sie zum Registrieren von FlowModel verwendet:

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

class MyPlugin extends Plugin {
  async load() {
    // FlowModel registrieren (Lazy-Loading-Schreibweise empfohlen)
    this.flowEngine.registerModelLoaders({
      HelloBlockModel: {
        loader: () => import('./models/HelloBlockModel'),
      },
    });
  }
}

FlowModel ist der Kern des visuellen Konfigurationssystems von NocoBase — wenn Ihr Component im Menü „Block / Feld / Aktion hinzufügen" erscheinen soll, müssen Sie es mit einem FlowModel verpacken. Ausführliche Verwendung siehe FlowEngine.

Weitere Fähigkeiten

Die folgenden Fähigkeiten kommen in fortgeschrittenen Szenarien zum Einsatz, hier kurz aufgeführt:

EigenschaftHinweis
ctx.modelAktuelle FlowModel-Instanz (verfügbar im Flow-Ausführungskontext)
ctx.refComponent-Referenz, in Verbindung mit ctx.onRefReady verwendbar
ctx.exit()Ausführung des aktuellen Flow beenden
ctx.defineProperty()Dem Kontext dynamisch eine benutzerdefinierte Eigenschaft hinzufügen
ctx.defineMethod()Dem Kontext dynamisch eine benutzerdefinierte Methode hinzufügen
ctx.useResource()Datenressourcen-Operationsschnittstelle abrufen
ctx.dataSourceManagerDatenquellen-Verwaltung

Detaillierte Verwendung dieser Fähigkeiten siehe vollständige FlowEngine-Dokumentation.